88# and executing models under various configuration flags.
99
1010import argparse
11+ import csv
1112import importlib
13+ import json
1214import logging
1315import os
1416import re
4850 QNN_TENSOR_TYPE_MAP ,
4951 to_edge_transform_and_lower_to_qnn ,
5052)
53+ from executorch .devtools import Inspector
5154from executorch .examples .qualcomm .qaihub_scripts .utils .utils import preprocess_binary
5255from executorch .exir import ExecutorchBackendConfig
5356from executorch .exir .passes .memory_planning_pass import MemoryPlanningPass
@@ -300,7 +303,13 @@ def execute(args):
300303 args .artifact ,
301304 verification = Verification .Minimal ,
302305 )
303- input_order_func = program .load_method (INPUT_ORDER )
306+ try :
307+ input_order_func = program .load_method (INPUT_ORDER )
308+ except Exception :
309+ logger .error (
310+ "Missing INPUT_ORDER in the .pte. The CLI execute command only supports .pte files generated by the CLI compile command, which preserves the input order."
311+ )
312+ exit (1 )
304313 input_order = input_order_func .execute ([])
305314
306315 # load input files
@@ -317,6 +326,8 @@ def execute(args):
317326 user_inputs .append (ordered_inputs )
318327 else :
319328 user_inputs .append (inputs )
329+ if args .profile :
330+ break
320331
321332 logger .info ("retrieving graph I/O" )
322333 # setup compiler spec
@@ -358,7 +369,8 @@ def execute(args):
358369 adb .push (inputs = user_inputs , backends = [backend_type ])
359370
360371 logger .info ("starting inference" )
361- adb .execute ()
372+ iteration = 100 if args .profile else 1
373+ adb .execute (iteration = iteration )
362374
363375 tmp_dir = f"{ args .output_folder } /tmp_outputs"
364376 os .makedirs (tmp_dir , exist_ok = True )
@@ -404,8 +416,22 @@ def post_process():
404416 )
405417 torch .save (output , f"{ output_result_folder } /output_{ output_index } .pt" )
406418
419+ def post_process_etdump ():
420+ etdump_path = f"{ args .output_folder } /etdump.etdp"
421+ csv_path = f"{ args .output_folder } /etdump.csv"
422+ json_path = f"{ args .output_folder } /performance.json"
423+ inspector = Inspector (etdump_path = etdump_path )
424+ inspector .save_data_to_tsv (csv_path )
425+ with open (csv_path , encoding = "utf-8" ) as csv_file :
426+ data = list (csv .DictReader (csv_file , delimiter = "\t " ))
427+ with open (json_path , "w" , encoding = "utf-8" ) as json_file :
428+ json .dump (data , json_file , indent = 4 )
429+
407430 logger .info ("collecting output data" )
408- adb .pull (host_output_path = tmp_dir , callback = post_process )
431+ if args .profile :
432+ adb .pull_etdump (args .output_folder , callback = post_process_etdump )
433+ else :
434+ adb .pull (host_output_path = tmp_dir , callback = post_process )
409435 shutil .rmtree (tmp_dir )
410436 logger .info (f"execution finished, please check { args .output_folder } for results" )
411437
@@ -633,6 +659,15 @@ def main():
633659 default = "htp" ,
634660 help = "Backend to be deployed ('htp'/'lpai' are currently supported)." ,
635661 )
662+ sub_execute .add_argument (
663+ "--profile" ,
664+ help = (
665+ "When enabled, only the first entry in input_list.txt is used for "
666+ "inference. The total number of inferences is fixed at 100. In "
667+ "this case, the outputs folder will not be pulled."
668+ ),
669+ action = "store_true" ,
670+ )
636671 sub_execute .set_defaults (callback = execute )
637672
638673 args = parser .parse_args ()
0 commit comments