From c4bd700a2dea47d63253ade40e91c40b069fa232 Mon Sep 17 00:00:00 2001 From: Jose Santos Date: Tue, 12 Mar 2024 12:15:39 -0500 Subject: [PATCH] Check for CI_VISIBLE_DEVICES num_devices - add vcopy_MI200 Signed-off-by: Jose Santos --- tests/test_profile_general.py | 96 ++++++++++++++++++---------------- tests/vcopy_MI100 | Bin 0 -> 39832 bytes tests/vcopy_MI200 | Bin 0 -> 40856 bytes 3 files changed, 52 insertions(+), 44 deletions(-) create mode 100755 tests/vcopy_MI100 create mode 100755 tests/vcopy_MI200 diff --git a/tests/test_profile_general.py b/tests/test_profile_general.py index c6380b0f8b..5924f934f7 100644 --- a/tests/test_profile_general.py +++ b/tests/test_profile_general.py @@ -18,7 +18,7 @@ import test_utils config = {} config["omniperf"] = SourceFileLoader("omniperf", "src/omniperf").load_module() config["kernel_name_1"] = "vecCopy(double*, double*, double*, int, int) [clone .kd]" -config["app_1"] = ["./tests/vcopy", "-n", "1048576", "-b", "256", "-i", "3"] +config["app_1"] = ["./tests/vcopy_MI100", "-n", "1048576", "-b", "256", "-i", "3"] config["cleanup"] = True config["COUNTER_LOGGING"] = False config["METRIC_COMPARE"] = False @@ -30,7 +30,7 @@ baseline_opts = ["omniperf", "profile", "-n", "app_1", "-VVV"] # app_1 = ["./sample/vcopy", "-n", "1048576", "-b", "256", "-i", "3"] num_kernels = 3 -num_devices = 4 +num_devices = 1 dispatch_id = 0 DEFAULT_ABS_DIFF = 15 @@ -255,13 +255,21 @@ def gpu_soc(): rocminfo = rocminfo.split("\n") print(rocminfo) soc_regex = re.compile(r"^\s*Name\s*:\s+ ([a-zA-Z0-9]+)\s*$", re.MULTILINE) - gpu_id = list(filter(soc_regex.match, rocminfo))[0].split()[1] + devices = list(filter(soc_regex.match, rocminfo)) + + num_devices = ( + len(devices) + if not "CI_VISIBLE_DEVICES" in os.environ + else os.environ["CI_VISIBLE_DEVICES"] + ) + gpu_id = devices[0].split()[1] if gpu_id == "gfx906": return "MI50" elif gpu_id == "gfx908": return "MI100" elif gpu_id == "gfx90a": + config["app_1"] = ["./tests/vcopy_MI200", "-n", "1048576", "-b", "256", "-i", "3"] return "MI200" elif gpu_id == "gfx900": return "vega10" @@ -455,7 +463,7 @@ def test_path(): test_utils.launch_omniperf(config, options, workload_dir) file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": print(sorted(list(file_dict.keys()))) assert sorted(list(file_dict.keys())) == ALL_CSVS_MI200 else: @@ -473,7 +481,7 @@ def test_no_roof(): test_utils.launch_omniperf(config, options, workload_dir) file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == [ "SQ_IFETCH_LEVEL.csv", "SQ_INST_LEVEL_LDS.csv", @@ -530,7 +538,7 @@ def test_kernel_names(): assert e.value.code == 0 file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == [ "empirRoof_gpu-0_fp32.pdf", "empirRoof_gpu-0_int8_fp16.pdf", @@ -567,7 +575,7 @@ def test_device_filter(): test_utils.launch_omniperf(config, options, workload_dir) file_dict = test_utils.check_csv_files(workload_dir, 1, num_kernels) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == ALL_CSVS_MI200 else: assert sorted(list(file_dict.keys())) == ALL_CSVS @@ -590,7 +598,7 @@ def test_kernel(): test_utils.launch_omniperf(config, options, workload_dir) file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == ALL_CSVS_MI200 else: assert sorted(list(file_dict.keys())) == ALL_CSVS @@ -611,7 +619,7 @@ def test_kernel_summaries(): test_utils.launch_omniperf(config, options, workload_dir) file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == ALL_CSVS_MI200 else: assert sorted(list(file_dict.keys())) == ALL_CSVS @@ -651,7 +659,7 @@ def test_block_SQ(): "sysinfo.csv", "timestamps.csv", ] - if soc == "mi200": + if soc == "MI200": expected_csvs = [ "SQ_IFETCH_LEVEL.csv", "SQ_INST_LEVEL_LDS.csv", @@ -685,7 +693,7 @@ def test_block_SQ(): file_dict, ) - test_utils.clean_output_dir(config["cleanup"], workload_dir) + # test_utils.clean_output_dir(config["cleanup"], workload_dir) @pytest.mark.block @@ -704,7 +712,7 @@ def test_block_SQC(): "sysinfo.csv", "timestamps.csv", ] - if soc == "mi200": + if soc == "MI200": expected_csvs.insert(5, "roofline.csv") assert sorted(list(file_dict.keys())) == expected_csvs @@ -738,7 +746,7 @@ def test_block_TA(): "sysinfo.csv", "timestamps.csv", ] - if soc == "mi200": + if soc == "MI200": expected_csvs.insert(9, "roofline.csv") assert sorted(list(file_dict.keys())) == expected_csvs @@ -767,7 +775,7 @@ def test_block_TD(): "sysinfo.csv", "timestamps.csv", ] - if soc == "mi200": + if soc == "MI200": expected_csvs = [ "pmc_perf.csv", "pmc_perf_0.csv", @@ -812,7 +820,7 @@ def test_block_TCP(): "sysinfo.csv", "timestamps.csv", ] - if soc == "mi200": + if soc == "MI200": expected_csvs.insert(11, "roofline.csv") assert sorted(list(file_dict.keys())) == expected_csvs @@ -849,7 +857,7 @@ def test_block_TCC(): "sysinfo.csv", "timestamps.csv", ] - if soc == "mi200": + if soc == "MI200": expected_csvs.insert(12, "roofline.csv") assert sorted(list(file_dict.keys())) == expected_csvs @@ -884,7 +892,7 @@ def test_block_SPI(): "sysinfo.csv", "timestamps.csv", ] - if soc == "mi200": + if soc == "MI200": expected_csvs.insert(10, "roofline.csv") assert sorted(list(file_dict.keys())) == expected_csvs @@ -916,7 +924,7 @@ def test_block_CPC(): "sysinfo.csv", "timestamps.csv", ] - if soc == "mi200": + if soc == "MI200": expected_csvs.insert(7, "roofline.csv") assert sorted(list(file_dict.keys())) == expected_csvs @@ -941,7 +949,7 @@ def test_block_CPF(): "sysinfo.csv", "timestamps.csv", ] - if soc == "mi200": + if soc == "MI200": expected_csvs.insert(5, "roofline.csv") assert sorted(list(file_dict.keys())) == expected_csvs @@ -980,7 +988,7 @@ def test_block_SQ_CPC(): "sysinfo.csv", "timestamps.csv", ] - if soc == "mi200": + if soc == "MI200": expected_csvs = [ "SQ_IFETCH_LEVEL.csv", "SQ_INST_LEVEL_LDS.csv", @@ -1043,7 +1051,7 @@ def test_block_SQ_TA(): "sysinfo.csv", "timestamps.csv", ] - if soc == "mi200": + if soc == "MI200": expected_csvs = [ "SQ_IFETCH_LEVEL.csv", "SQ_INST_LEVEL_LDS.csv", @@ -1101,7 +1109,7 @@ def test_block_SQ_SPI(): "sysinfo.csv", "timestamps.csv", ] - if soc == "mi200": + if soc == "MI200": expected_csvs = [ "SQ_IFETCH_LEVEL.csv", "SQ_INST_LEVEL_LDS.csv", @@ -1163,7 +1171,7 @@ def test_block_SQ_SQC_TCP_CPC(): "sysinfo.csv", "timestamps.csv", ] - if soc == "mi200": + if soc == "MI200": expected_csvs = [ "SQ_IFETCH_LEVEL.csv", "SQ_INST_LEVEL_LDS.csv", @@ -1223,7 +1231,7 @@ def test_block_SQ_SPI_TA_TCC_CPF(): "sysinfo.csv", "timestamps.csv", ] - if soc == "mi200": + if soc == "MI200": expected_csvs = [ "SQ_IFETCH_LEVEL.csv", "SQ_INST_LEVEL_LDS.csv", @@ -1266,7 +1274,7 @@ def test_dispatch_0(): test_utils.launch_omniperf(config, options, workload_dir) file_dict = test_utils.check_csv_files(workload_dir, num_devices, 1) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == ALL_CSVS_MI200 else: assert sorted(list(file_dict.keys())) == ALL_CSVS @@ -1291,7 +1299,7 @@ def test_dispatch_0_1(): test_utils.launch_omniperf(config, options, workload_dir) file_dict = test_utils.check_csv_files(workload_dir, num_devices, 2) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == ALL_CSVS_MI200 else: assert sorted(list(file_dict.keys())) == ALL_CSVS @@ -1313,7 +1321,7 @@ def test_dispatch_2(): test_utils.launch_omniperf(config, options, workload_dir) file_dict = test_utils.check_csv_files(workload_dir, num_devices, 1) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == ALL_CSVS_MI200 else: assert sorted(list(file_dict.keys())) == ALL_CSVS @@ -1338,7 +1346,7 @@ def test_kernel_verbose_0(): test_utils.launch_omniperf(config, options, workload_dir) file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == ALL_CSVS_MI200 else: assert sorted(list(file_dict.keys())) == ALL_CSVS @@ -1359,7 +1367,7 @@ def test_kernel_verbose_1(): test_utils.launch_omniperf(config, options, workload_dir) file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == ALL_CSVS_MI200 else: assert sorted(list(file_dict.keys())) == ALL_CSVS @@ -1380,7 +1388,7 @@ def test_kernel_verbose_2(): test_utils.launch_omniperf(config, options, workload_dir) file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == ALL_CSVS_MI200 else: assert sorted(list(file_dict.keys())) == ALL_CSVS @@ -1401,7 +1409,7 @@ def test_kernel_verbose_3(): test_utils.launch_omniperf(config, options, workload_dir) file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == ALL_CSVS_MI200 else: assert sorted(list(file_dict.keys())) == ALL_CSVS @@ -1422,7 +1430,7 @@ def test_kernel_verbose_4(): test_utils.launch_omniperf(config, options, workload_dir) file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == ALL_CSVS_MI200 else: assert sorted(list(file_dict.keys())) == ALL_CSVS @@ -1443,7 +1451,7 @@ def test_kernel_verbose_5(): test_utils.launch_omniperf(config, options, workload_dir) file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == ALL_CSVS_MI200 else: assert sorted(list(file_dict.keys())) == ALL_CSVS @@ -1464,7 +1472,7 @@ def test_join_type_grid(): test_utils.launch_omniperf(config, options, workload_dir) file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == ALL_CSVS_MI200 else: assert sorted(list(file_dict.keys())) == ALL_CSVS @@ -1486,7 +1494,7 @@ def test_join_type_kernel(): file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == ALL_CSVS_MI200 else: assert sorted(list(file_dict.keys())) == ALL_CSVS @@ -1517,7 +1525,7 @@ def test_sort_dispatches(): file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == ROOF_ONLY_FILES else: assert sorted(list(file_dict.keys())) == ALL_CSVS @@ -1547,7 +1555,7 @@ def test_sort_kernels(): assert e.value.code == 0 file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": assert sorted(list(file_dict.keys())) == ROOF_ONLY_FILES else: assert sorted(list(file_dict.keys())) == ALL_CSVS @@ -1577,7 +1585,7 @@ def test_mem_levels_HBM(): assert e.value.code == 0 file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": print(sorted(list(file_dict.keys()))) assert sorted(list(file_dict.keys())) == ROOF_ONLY_FILES else: @@ -1608,7 +1616,7 @@ def test_mem_levels_L2(): assert e.value.code == 0 file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": print(sorted(list(file_dict.keys()))) assert sorted(list(file_dict.keys())) == ROOF_ONLY_FILES else: @@ -1639,7 +1647,7 @@ def test_mem_levels_vL1D(): assert e.value.code == 0 file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": print(sorted(list(file_dict.keys()))) assert sorted(list(file_dict.keys())) == ROOF_ONLY_FILES else: @@ -1670,7 +1678,7 @@ def test_mem_levels_LDS(): assert e.value.code == 0 file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": print(sorted(list(file_dict.keys()))) assert sorted(list(file_dict.keys())) == ROOF_ONLY_FILES else: @@ -1701,7 +1709,7 @@ def test_mem_levels_HBM_LDS(): assert e.value.code == 0 file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": print(sorted(list(file_dict.keys()))) assert sorted(list(file_dict.keys())) == ROOF_ONLY_FILES else: @@ -1732,7 +1740,7 @@ def test_mem_levels_vL1D_LDS(): assert e.value.code == 0 file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": print(sorted(list(file_dict.keys()))) assert sorted(list(file_dict.keys())) == ROOF_ONLY_FILES else: @@ -1762,7 +1770,7 @@ def test_mem_levels_L2_vL1D_LDS(): assert e.value.code == 0 file_dict = test_utils.check_csv_files(workload_dir, num_devices, num_kernels) - if soc == "mi200": + if soc == "MI200": print(sorted(list(file_dict.keys()))) assert sorted(list(file_dict.keys())) == ROOF_ONLY_FILES else: diff --git a/tests/vcopy_MI100 b/tests/vcopy_MI100 new file mode 100755 index 0000000000000000000000000000000000000000..734c218be8a433260992a0faad54f68df6def085 GIT binary patch literal 39832 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