From 2924b47e40e946758c49c7a33ce20a740aa6e0d5 Mon Sep 17 00:00:00 2001 From: ManasviGoyal Date: Fri, 12 Jan 2024 16:41:21 +0100 Subject: [PATCH 01/16] feat: generate unit tests for cuda --- dev/generate-tests.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/dev/generate-tests.py b/dev/generate-tests.py index fb0ba99b29..51803301e4 100644 --- a/dev/generate-tests.py +++ b/dev/generate-tests.py @@ -658,6 +658,37 @@ def gencudakerneltests(specdict): f.write(" " * 4 + f"assert {arg} == pytest_{arg}\n") f.write("\n") +def gencudaunittests(): + print("Generating Unit Tests for CUDA kernels") + + unit_tests_cuda_kernels = os.path.join(CURRENT_DIR, "..", "tests-cuda-kernels-explicit") + if os.path.exists(unit_tests_cuda_kernels): + shutil.rmtree(unit_tests_cuda_kernels) + os.mkdir(unit_tests_cuda_kernels) + with open(os.path.join(unit_tests_cuda_kernels, "__init__.py"), "w") as f: + f.write( + f"""# AUTO GENERATED ON {reproducible_datetime()} +# DO NOT EDIT BY HAND! +# +# To regenerate file, run +# +# python dev/generate-tests.py +# + +# fmt: off + +""" + ) + with open(os.path.join(CURRENT_DIR, "..", "kernel-test-data.json")) as f: + data = json.load(f)["unit-tests"] + for function in data: + num = 0 + func = "test_cuda" + function["name"] + ".py" + with open( + os.path.join(CURRENT_DIR, "..", "tests-cuda-kernels-explicit", func), + "w", + ) as file: + file.write("import pytest\nimport cupy\n\n") def genunittests(): print("Generating Unit Tests") @@ -715,3 +746,4 @@ def evalkernels(): gencpukerneltests(specdict) genunittests() gencudakerneltests(specdict) + gencudaunittests() From 4dabd94b482ec19a91f0a27b308bf6ebe3855455 Mon Sep 17 00:00:00 2001 From: ManasviGoyal Date: Mon, 15 Jan 2024 17:21:30 +0100 Subject: [PATCH 02/16] feat: complete the function --- dev/generate-tests.py | 134 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 128 insertions(+), 6 deletions(-) diff --git a/dev/generate-tests.py b/dev/generate-tests.py index 51803301e4..41ba42a3ad 100644 --- a/dev/generate-tests.py +++ b/dev/generate-tests.py @@ -658,9 +658,18 @@ def gencudakerneltests(specdict): f.write(" " * 4 + f"assert {arg} == pytest_{arg}\n") f.write("\n") -def gencudaunittests(): +def cudaunittestmap(): + with open(os.path.join(CURRENT_DIR, "..", "kernel-test-data.json")) as f: + data = json.load(f)["unit-tests"] + cuda_unit_tests_map = {} + for function in data: + cuda_unit_tests_map[function["name"]] = function["tests"] + return cuda_unit_tests_map + +def gencudaunittests(specdict): print("Generating Unit Tests for CUDA kernels") + cuda_unit_tests = cudaunittestmap() unit_tests_cuda_kernels = os.path.join(CURRENT_DIR, "..", "tests-cuda-kernels-explicit") if os.path.exists(unit_tests_cuda_kernels): shutil.rmtree(unit_tests_cuda_kernels) @@ -681,14 +690,127 @@ def gencudaunittests(): ) with open(os.path.join(CURRENT_DIR, "..", "kernel-test-data.json")) as f: data = json.load(f)["unit-tests"] - for function in data: + + for spec in specdict.values(): + if spec.templatized_kernel_name in cuda_kernels_tests and spec.templatized_kernel_name in list(cuda_unit_tests.keys()): + func = "test_cuda" + spec.templatized_kernel_name + ".py" num = 0 - func = "test_cuda" + function["name"] + ".py" with open( - os.path.join(CURRENT_DIR, "..", "tests-cuda-kernels-explicit", func), + os.path.join(CURRENT_DIR, "..", "tests-cuda-kernels-explicit", func), "w", ) as file: - file.write("import pytest\nimport cupy\n\n") + file.write( + f"""# AUTO GENERATED ON {reproducible_datetime()} +# DO NOT EDIT BY HAND! +# +# To regenerate file, run +# +# python dev/generate-tests.py +# + +# fmt: off + +""" + ) + + file.write( + "import cupy\n" + "import pytest\n\n" + "import awkward as ak\n" + "import awkward._connect.cuda as ak_cu\n" + "from awkward._backends.cupy import CupyBackend\n\n" + "cupy_backend = CupyBackend.instance()\n\n" + ) + for test in cuda_unit_tests[spec.templatized_kernel_name]: + num += 1 + funcName = "def test_" + spec.templatized_kernel_name + "_" + str(num) + "():\n" + file.write(funcName) + dtypes = [] + for arg, val in test["outputs"].items(): + typename = remove_const( + next( + argument + for argument in spec.args + if argument.name == arg + ).typename + ) + if "List" not in typename: + file.write(" " * 4 + arg + " = " + str([123] * len(val)) + "\n") + if "List" in typename: + count = typename.count("List") + typename = gettypename(typename) + if typename == "bool" or typename == "float": + typename = typename + "_" + if count == 1: + file.write( + " " * 4 + + "{} = cupy.array({}, dtype=cupy.{})\n".format( + arg, str([123] * len(val)), typename + ) + ) + dtypes.append("cupy." + typename) + elif count == 2: + raise NotImplementedError + for arg, val in test["inputs"].items(): + typename = remove_const( + next( + argument + for argument in spec.args + if argument.name == arg + ).typename + ) + if "List" not in typename: + file.write(" " * 4 + arg + " = " + str(val) + "\n") + if "List" in typename: + count = typename.count("List") + typename = gettypename(typename) + if typename == "bool" or typename == "float": + typename = typename + "_" + if count == 1: + file.write( + " " * 4 + + "{} = cupy.array({}, dtype=cupy.{})\n".format( + arg, val, typename + ) + ) + dtypes.append("cupy." + typename) + elif count == 2: + raise NotImplementedError + + cuda_string = ( + "funcC = cupy_backend['" + + spec.templatized_kernel_name + + "', {}]\n".format(", ".join(dtypes)) + ) + file.write(" " * 4 + cuda_string) + args = "" + count = 0 + for arg in spec.args: + if count == 0: + args += arg.name + count += 1 + else: + args += ", " + arg.name + file.write(" " * 4 + "funcC(" + args + ")\n") + file.write( + """ + try: + ak_cu.synchronize_cuda() + except: + pytest.fail("This test case shouldn't have raised an error") +""" + ) + for arg, val in test["outputs"].items(): + file.write(" " * 4 + "pytest_" + arg + " = " + str(val) + "\n") + if isinstance(val, list): + file.write( + " " * 4 + + f"assert cupy.array_equal({arg}[:len(pytest_{arg})], cupy.array(pytest_{arg}))\n" + ) + else: + file.write(" " * 4 + f"assert {arg} == pytest_{arg}\n") + file.write("\n") + def genunittests(): print("Generating Unit Tests") @@ -746,4 +868,4 @@ def evalkernels(): gencpukerneltests(specdict) genunittests() gencudakerneltests(specdict) - gencudaunittests() + gencudaunittests(specdict) From 8773118ba88bac4db8765fa90dd63d416c3428da Mon Sep 17 00:00:00 2001 From: ManasviGoyal Date: Mon, 15 Jan 2024 17:24:26 +0100 Subject: [PATCH 03/16] refactor: remove data variable --- dev/generate-tests.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/generate-tests.py b/dev/generate-tests.py index 41ba42a3ad..b96390046d 100644 --- a/dev/generate-tests.py +++ b/dev/generate-tests.py @@ -688,8 +688,6 @@ def gencudaunittests(specdict): """ ) - with open(os.path.join(CURRENT_DIR, "..", "kernel-test-data.json")) as f: - data = json.load(f)["unit-tests"] for spec in specdict.values(): if spec.templatized_kernel_name in cuda_kernels_tests and spec.templatized_kernel_name in list(cuda_unit_tests.keys()): From d694e77b1b4b21585e05d3afe2d7b104242efd98 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 16:25:11 +0000 Subject: [PATCH 04/16] style: pre-commit fixes --- dev/generate-tests.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/dev/generate-tests.py b/dev/generate-tests.py index b96390046d..8ed65b37cb 100644 --- a/dev/generate-tests.py +++ b/dev/generate-tests.py @@ -658,6 +658,7 @@ def gencudakerneltests(specdict): f.write(" " * 4 + f"assert {arg} == pytest_{arg}\n") f.write("\n") + def cudaunittestmap(): with open(os.path.join(CURRENT_DIR, "..", "kernel-test-data.json")) as f: data = json.load(f)["unit-tests"] @@ -666,11 +667,14 @@ def cudaunittestmap(): cuda_unit_tests_map[function["name"]] = function["tests"] return cuda_unit_tests_map + def gencudaunittests(specdict): print("Generating Unit Tests for CUDA kernels") cuda_unit_tests = cudaunittestmap() - unit_tests_cuda_kernels = os.path.join(CURRENT_DIR, "..", "tests-cuda-kernels-explicit") + unit_tests_cuda_kernels = os.path.join( + CURRENT_DIR, "..", "tests-cuda-kernels-explicit" + ) if os.path.exists(unit_tests_cuda_kernels): shutil.rmtree(unit_tests_cuda_kernels) os.mkdir(unit_tests_cuda_kernels) @@ -690,7 +694,10 @@ def gencudaunittests(specdict): ) for spec in specdict.values(): - if spec.templatized_kernel_name in cuda_kernels_tests and spec.templatized_kernel_name in list(cuda_unit_tests.keys()): + if ( + spec.templatized_kernel_name in cuda_kernels_tests + and spec.templatized_kernel_name in list(cuda_unit_tests.keys()) + ): func = "test_cuda" + spec.templatized_kernel_name + ".py" num = 0 with open( @@ -698,7 +705,7 @@ def gencudaunittests(specdict): "w", ) as file: file.write( - f"""# AUTO GENERATED ON {reproducible_datetime()} + f"""# AUTO GENERATED ON {reproducible_datetime()} # DO NOT EDIT BY HAND! # # To regenerate file, run @@ -721,7 +728,13 @@ def gencudaunittests(specdict): ) for test in cuda_unit_tests[spec.templatized_kernel_name]: num += 1 - funcName = "def test_" + spec.templatized_kernel_name + "_" + str(num) + "():\n" + funcName = ( + "def test_" + + spec.templatized_kernel_name + + "_" + + str(num) + + "():\n" + ) file.write(funcName) dtypes = [] for arg, val in test["outputs"].items(): @@ -733,7 +746,9 @@ def gencudaunittests(specdict): ).typename ) if "List" not in typename: - file.write(" " * 4 + arg + " = " + str([123] * len(val)) + "\n") + file.write( + " " * 4 + arg + " = " + str([123] * len(val)) + "\n" + ) if "List" in typename: count = typename.count("List") typename = gettypename(typename) From 34b2a4cb21e2a7a5b679a5c2dfc81174fed7c545 Mon Sep 17 00:00:00 2001 From: ManasviGoyal Date: Wed, 17 Jan 2024 15:23:10 +0100 Subject: [PATCH 05/16] fix: dtypes order --- dev/generate-tests.py | 163 ++++++++++++++++++++++++------------------ 1 file changed, 93 insertions(+), 70 deletions(-) diff --git a/dev/generate-tests.py b/dev/generate-tests.py index 8ed65b37cb..3a97eba6f4 100644 --- a/dev/generate-tests.py +++ b/dev/generate-tests.py @@ -698,7 +698,7 @@ def gencudaunittests(specdict): spec.templatized_kernel_name in cuda_kernels_tests and spec.templatized_kernel_name in list(cuda_unit_tests.keys()) ): - func = "test_cuda" + spec.templatized_kernel_name + ".py" + func = "test_cuda" + spec.name + ".py" num = 0 with open( os.path.join(CURRENT_DIR, "..", "tests-cuda-kernels-explicit", func), @@ -728,42 +728,18 @@ def gencudaunittests(specdict): ) for test in cuda_unit_tests[spec.templatized_kernel_name]: num += 1 - funcName = ( - "def test_" - + spec.templatized_kernel_name - + "_" - + str(num) - + "():\n" - ) - file.write(funcName) + funcName = "def test_" + spec.name + "_" + str(num) + "():\n" dtypes = [] - for arg, val in test["outputs"].items(): - typename = remove_const( - next( - argument - for argument in spec.args - if argument.name == arg - ).typename - ) - if "List" not in typename: - file.write( - " " * 4 + arg + " = " + str([123] * len(val)) + "\n" - ) + for arg in spec.args: + typename = remove_const(arg.typename) if "List" in typename: count = typename.count("List") typename = gettypename(typename) if typename == "bool" or typename == "float": typename = typename + "_" if count == 1: - file.write( - " " * 4 - + "{} = cupy.array({}, dtype=cupy.{})\n".format( - arg, str([123] * len(val)), typename - ) - ) dtypes.append("cupy." + typename) - elif count == 2: - raise NotImplementedError + flag = True for arg, val in test["inputs"].items(): typename = remove_const( next( @@ -772,57 +748,104 @@ def gencudaunittests(specdict): if argument.name == arg ).typename ) - if "List" not in typename: - file.write(" " * 4 + arg + " = " + str(val) + "\n") - if "List" in typename: - count = typename.count("List") - typename = gettypename(typename) - if typename == "bool" or typename == "float": - typename = typename + "_" - if count == 1: + if "List[uint" in typename and (any(n < 0 for n in val)): + flag = False + file.write( + "@pytest.mark.skip(reason='Unable to generate any tests for kernel')\n" + ) + file.write(funcName) + file.write( + " " * 4 + + "raise NotImplementedError('Unable to generate any tests for kernel')\n\n" + ) + if flag is True: + file.write(funcName) + for arg, val in test["outputs"].items(): + typename = remove_const( + next( + argument + for argument in spec.args + if argument.name == arg + ).typename + ) + if "List" not in typename: file.write( - " " * 4 - + "{} = cupy.array({}, dtype=cupy.{})\n".format( - arg, val, typename - ) + " " * 4 + arg + " = " + str([123] * len(val)) + "\n" ) - dtypes.append("cupy." + typename) - elif count == 2: - raise NotImplementedError + if "List" in typename: + count = typename.count("List") + typename = gettypename(typename) + if typename == "bool" or typename == "float": + typename = typename + "_" + if count == 1: + file.write( + " " * 4 + + "{} = cupy.array({}, dtype=cupy.{})\n".format( + arg, str([123] * len(val)), typename + ) + ) + elif count == 2: + raise NotImplementedError + for arg, val in test["inputs"].items(): + typename = remove_const( + next( + argument + for argument in spec.args + if argument.name == arg + ).typename + ) + if "List" not in typename: + file.write(" " * 4 + arg + " = " + str(val) + "\n") + if "List" in typename: + count = typename.count("List") + typename = gettypename(typename) + if typename == "bool" or typename == "float": + typename = typename + "_" + if count == 1: + file.write( + " " * 4 + + "{} = cupy.array({}, dtype=cupy.{})\n".format( + arg, val, typename + ) + ) + elif count == 2: + raise NotImplementedError - cuda_string = ( - "funcC = cupy_backend['" - + spec.templatized_kernel_name - + "', {}]\n".format(", ".join(dtypes)) - ) - file.write(" " * 4 + cuda_string) - args = "" - count = 0 - for arg in spec.args: - if count == 0: - args += arg.name - count += 1 - else: - args += ", " + arg.name - file.write(" " * 4 + "funcC(" + args + ")\n") - file.write( - """ + cuda_string = ( + "funcC = cupy_backend['" + + spec.templatized_kernel_name + + "', {}]\n".format(", ".join(dtypes)) + ) + file.write(" " * 4 + cuda_string) + args = "" + count = 0 + for arg in spec.args: + if count == 0: + args += arg.name + count += 1 + else: + args += ", " + arg.name + file.write(" " * 4 + "funcC(" + args + ")\n") + file.write( + """ try: ak_cu.synchronize_cuda() except: pytest.fail("This test case shouldn't have raised an error") """ - ) - for arg, val in test["outputs"].items(): - file.write(" " * 4 + "pytest_" + arg + " = " + str(val) + "\n") - if isinstance(val, list): + ) + for arg, val in test["outputs"].items(): file.write( - " " * 4 - + f"assert cupy.array_equal({arg}[:len(pytest_{arg})], cupy.array(pytest_{arg}))\n" + " " * 4 + "pytest_" + arg + " = " + str(val) + "\n" ) - else: - file.write(" " * 4 + f"assert {arg} == pytest_{arg}\n") - file.write("\n") + if isinstance(val, list): + file.write( + " " * 4 + + f"assert cupy.array_equal({arg}[:len(pytest_{arg})], cupy.array(pytest_{arg}))\n" + ) + else: + file.write(" " * 4 + f"assert {arg} == pytest_{arg}\n") + file.write("\n") def genunittests(): From e58c0cfc0f6a957ac1ff3ec23790ff7c33dd3ed4 Mon Sep 17 00:00:00 2001 From: ManasviGoyal Date: Thu, 18 Jan 2024 11:51:58 +0100 Subject: [PATCH 06/16] refactor: add status to unit-tests --- kernel-test-data.json | 84 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/kernel-test-data.json b/kernel-test-data.json index 60f195bf47..6b482fef49 100644 --- a/kernel-test-data.json +++ b/kernel-test-data.json @@ -289,6 +289,7 @@ "unit-tests": [ { "name": "awkward_missing_repeat", + "status": false, "tests": [ { "error": false, @@ -800,6 +801,7 @@ }, { "name": "awkward_index_rpad_and_clip_axis0", + "status": false, "tests": [ { "error": false, @@ -913,6 +915,7 @@ }, { "name": "awkward_BitMaskedArray_to_ByteMaskedArray", + "status": false, "tests": [ { "error": false, @@ -951,6 +954,7 @@ }, { "name": "awkward_ByteMaskedArray_getitem_nextcarry", + "status": false, "tests": [ { "error": false, @@ -976,6 +980,7 @@ }, { "name": "awkward_ByteMaskedArray_getitem_nextcarry_outindex", + "status": false, "tests": [ { "error": false, @@ -1010,6 +1015,7 @@ }, { "name": "awkward_ByteMaskedArray_numnull", + "status": false, "tests": [ { "error": false, @@ -1185,6 +1191,7 @@ }, { "name": "awkward_ByteMaskedArray_toIndexedOptionArray", + "status": false, "tests": [ { "error": false, @@ -1210,6 +1217,7 @@ }, { "name": "awkward_IndexedArray_flatten_nextcarry", + "status": false, "tests": [ { "error": false, @@ -1225,6 +1233,7 @@ }, { "name": "awkward_IndexedArray_getitem_nextcarry", + "status": false, "tests": [ { "error": false, @@ -1500,6 +1509,7 @@ }, { "name": "awkward_IndexedArray_getitem_nextcarry_outindex", + "status": false, "tests": [ { "error": false, @@ -1527,6 +1537,7 @@ }, { "name": "awkward_IndexedArray_numnull", + "status": false, "tests": [ { "error": false, @@ -1649,6 +1660,7 @@ }, { "name": "awkward_ListArray_broadcast_tooffsets", + "status": false, "tests": [ { "error": false, @@ -2782,6 +2794,7 @@ }, { "name": "awkward_ListArray_compact_offsets", + "status": false, "tests": [ { "error": false, @@ -3577,6 +3590,7 @@ }, { "name": "awkward_RegularArray_localindex", + "status": false, "tests": [ { "error": false, @@ -3600,6 +3614,7 @@ }, { "name": "awkward_RegularArray_rpad_and_clip_axis1", + "status": false, "tests": [ { "error": false, @@ -3675,6 +3690,7 @@ }, { "name": "awkward_RegularArray_getitem_carry", + "status": false, "tests": [ { "error": false, @@ -4120,6 +4136,7 @@ }, { "name": "awkward_RegularArray_getitem_jagged_expand", + "status": false, "tests": [ { "error": false, @@ -4415,6 +4432,7 @@ }, { "name": "awkward_RegularArray_getitem_next_array", + "status": false, "tests": [ { "error": false, @@ -5452,6 +5470,7 @@ }, { "name": "awkward_RegularArray_getitem_next_array_advanced", + "status": false, "tests": [ { "error": false, @@ -5639,6 +5658,7 @@ }, { "name": "awkward_RegularArray_getitem_next_array_regularize", + "status": false, "tests": [ { "error": false, @@ -6434,6 +6454,7 @@ }, { "name": "awkward_RegularArray_getitem_next_at", + "status": false, "tests": [ { "error": false, @@ -6649,6 +6670,7 @@ }, { "name": "awkward_RegularArray_getitem_next_range", + "status": false, "tests": [ { "error": false, @@ -7266,6 +7288,7 @@ }, { "name": "awkward_RegularArray_getitem_next_range_spreadadvanced", + "status": false, "tests": [ { "error": false, @@ -7291,6 +7314,7 @@ }, { "name": "awkward_ListOffsetArray_flatten_offsets", + "status": false, "tests": [ { "error": false, @@ -7604,6 +7628,7 @@ }, { "name": "awkward_ListOffsetArray_toRegularArray", + "status": false, "tests": [ { "error": false, @@ -7654,6 +7679,7 @@ }, { "name": "awkward_MaskedArray_getitem_next_jagged_project", + "status": false, "tests": [ { "error": false, @@ -7703,6 +7729,7 @@ }, { "name": "awkward_ListOffsetArray_reduce_nonlocal_maxcount_offsetscopy_64", + "status": false, "tests": [ { "error": false, @@ -8005,6 +8032,7 @@ }, { "name": "awkward_ByteMaskedArray_overlay_mask", + "status": false, "tests": [ { "error": false, @@ -8021,6 +8049,7 @@ }, { "name": "awkward_IndexedArray_flatten_none2empty", + "status": false, "tests": [ { "error": false, @@ -8103,6 +8132,7 @@ }, { "name": "awkward_IndexedArray_reduce_next_64", + "status": false, "tests": [ { "error": false, @@ -8229,6 +8259,7 @@ }, { "name": "awkward_IndexedArray_simplify", + "status": false, "tests": [ { "error": false, @@ -8608,6 +8639,7 @@ }, { "name": "awkward_IndexedArray_validity", + "status": false, "tests": [ { "error": false, @@ -8993,6 +9025,7 @@ }, { "name": "awkward_IndexedOptionArray_rpad_and_clip_mask_axis1", + "status": false, "tests": [ { "error": false, @@ -9007,6 +9040,7 @@ }, { "name": "awkward_index_rpad_and_clip_axis1", + "status": false, "tests": [ { "error": false, @@ -9142,6 +9176,7 @@ }, { "name": "awkward_ListArray_combinations_length", + "status": false, "tests": [ { "error": false, @@ -9231,6 +9266,7 @@ }, { "name": "awkward_ListArray_getitem_jagged_carrylen", + "status": false, "tests": [ { "error": false, @@ -9551,6 +9587,7 @@ }, { "name": "awkward_ListArray_getitem_jagged_descend", + "status": false, "tests": [ { "error": false, @@ -9600,6 +9637,7 @@ }, { "name": "awkward_ListArray_getitem_jagged_expand", + "status": false, "tests": [ { "error": false, @@ -9631,6 +9669,7 @@ }, { "name": "awkward_ListArray_getitem_next_array", + "status": false, "tests": [ { "error": false, @@ -9706,6 +9745,7 @@ }, { "name": "awkward_ListArray_min_range", + "status": false, "tests": [ { "error": false, @@ -9751,6 +9791,7 @@ }, { "name": "awkward_ListArray_rpad_and_clip_length_axis1", + "status": false, "tests": [ { "error": false, @@ -9877,6 +9918,7 @@ }, { "name": "awkward_ListArray_validity", + "status": false, "tests": [ { "error": false, @@ -10440,6 +10482,7 @@ }, { "name": "awkward_ListArray_getitem_jagged_apply", + "status": false, "tests": [ { "error": false, @@ -10805,6 +10848,7 @@ }, { "name": "awkward_UnionArray_regular_index", + "status": false, "tests": [ { "error": false, @@ -10843,6 +10887,7 @@ }, { "name": "awkward_UnionArray_regular_index_getsize", + "status": false, "tests": [ { "error": false, @@ -10875,6 +10920,7 @@ }, { "name": "awkward_IndexedArray_fill", + "status": false, "tests": [ { "error": false, @@ -10950,6 +10996,7 @@ }, { "name": "awkward_ListArray_fill", + "status": false, "tests": [ { "error": false, @@ -11095,6 +11142,7 @@ }, { "name": "awkward_UnionArray_fillindex", + "status": false, "tests": [ { "error": false, @@ -11120,6 +11168,7 @@ }, { "name": "awkward_UnionArray_validity", + "status": false, "tests": [ { "error": false, @@ -11185,6 +11234,7 @@ }, { "name": "awkward_ByteMaskedArray_reduce_next_nonlocal_nextshifts_64", + "status": false, "tests": [ { "error": false, @@ -11200,6 +11250,7 @@ }, { "name": "awkward_IndexedArray_index_of_nulls", + "status": false, "tests": [ { "error": false, @@ -11347,6 +11398,7 @@ }, { "name": "awkward_IndexedArray_reduce_next_fix_offsets_64", + "status": false, "tests": [ { "error": false, @@ -11422,6 +11474,7 @@ }, { "name": "awkward_IndexedArray_reduce_next_nonlocal_nextshifts_64", + "status": false, "tests": [ { "error": false, @@ -11541,6 +11594,7 @@ }, { "name": "awkward_IndexedArray_reduce_next_nonlocal_nextshifts_fromshifts_64", + "status": false, "tests": [ { "error": false, @@ -11609,6 +11663,7 @@ }, { "name": "awkward_ListArray_getitem_next_array_advanced", + "status": false, "tests": [ { "error": false, @@ -12340,6 +12395,7 @@ }, { "name": "awkward_ListArray_getitem_next_at", + "status": false, "tests": [ { "error": false, @@ -12907,6 +12963,7 @@ }, { "name": "awkward_ListArray_getitem_next_range_counts", + "status": false, "tests": [ { "error": false, @@ -12930,6 +12987,7 @@ }, { "name": "awkward_ListArray_localindex", + "status": false, "tests": [ { "error": false, @@ -13023,6 +13081,7 @@ }, { "name": "awkward_ListArray_rpad_axis1", + "status": false, "tests": [ { "error": false, @@ -13171,6 +13230,7 @@ }, { "name": "awkward_ListOffsetArray_reduce_local_outoffsets_64", + "status": false, "tests": [ { "error": false, @@ -13365,6 +13425,7 @@ }, { "name": "awkward_ListOffsetArray_reduce_nonlocal_nextshifts_64", + "status": false, "tests": [ { "error": false, @@ -13835,6 +13896,7 @@ }, { "name": "awkward_ListOffsetArray_reduce_nonlocal_nextstarts_64", + "status": false, "tests": [ { "error": false, @@ -14104,6 +14166,7 @@ }, { "name": "awkward_ListOffsetArray_reduce_nonlocal_outstartsstops_64", + "status": false, "tests": [ { "error": false, @@ -14362,6 +14425,7 @@ }, { "name": "awkward_NumpyArray_reduce_mask_ByteMaskedArray_64", + "status": false, "tests": [ { "error": false, @@ -14682,6 +14746,7 @@ }, { "name": "awkward_UnionArray_fillna", + "status": false, "tests": [ { "error": false, @@ -14828,6 +14893,7 @@ }, { "name": "awkward_UnionArray_filltags", + "status": false, "tests": [ { "error": false, @@ -14844,6 +14910,7 @@ }, { "name": "awkward_UnionArray_project", + "status": false, "tests": [ { "error": false, @@ -14995,6 +15062,7 @@ }, { "name": "awkward_UnionArray_simplify_one", + "status": false, "tests": [ { "error": false, @@ -15101,6 +15169,7 @@ }, { "name": "awkward_localindex", + "status": false, "tests": [ { "error": false, @@ -15139,6 +15208,7 @@ }, { "name": "awkward_BitMaskedArray_to_IndexedOptionArray", + "status": false, "tests": [ { "error": false, @@ -15166,6 +15236,7 @@ }, { "name": "awkward_ListArray_getitem_jagged_shrink", + "status": false, "tests": [ { "error": false, @@ -15231,6 +15302,7 @@ }, { "name": "awkward_Content_getitem_next_missing_jagged_getmaskstartstop", + "status": false, "tests": [ { "error": false, @@ -15500,6 +15572,7 @@ }, { "name": "awkward_reduce_sum_bool", + "status": false, "tests": [ { "error": false, @@ -15585,6 +15658,7 @@ }, { "name": "awkward_reduce_prod_bool", + "status": false, "tests": [ { "error": false, @@ -15800,6 +15874,7 @@ }, { "name": "awkward_reduce_argmax", + "status": false, "tests": [ { "error": false, @@ -15915,6 +15990,7 @@ }, { "name": "awkward_reduce_max", + "status": false, "tests": [ { "error": false, @@ -16052,6 +16128,7 @@ }, { "name": "awkward_reduce_countnonzero", + "status": false, "tests": [ { "error": false, @@ -16117,6 +16194,7 @@ }, { "name": "awkward_reduce_count_64", + "status": false, "tests": [ { "error": false, @@ -16392,6 +16470,7 @@ }, { "name": "awkward_reduce_sum", + "status": false, "tests": [ { "error": false, @@ -16687,6 +16766,7 @@ }, { "name": "awkward_reduce_prod", + "status": false, "tests": [ { "error": false, @@ -17272,6 +17352,7 @@ }, { "name": "awkward_reduce_min", + "status": false, "tests": [ { "error": false, @@ -17420,6 +17501,7 @@ }, { "name": "awkward_reduce_argmin", + "status": false, "tests": [ { "error": false, @@ -17676,6 +17758,7 @@ }, { "name": "awkward_UnionArray_fillindex_count", + "status": false, "tests": [ { "error": false, @@ -17753,6 +17836,7 @@ }, { "name": "awkward_UnionArray_simplify", + "status": false, "tests": [ { "error": false, From e012af84ec88a0c93a1afe08533a4d24fc99dcc4 Mon Sep 17 00:00:00 2001 From: ManasviGoyal Date: Thu, 18 Jan 2024 11:53:24 +0100 Subject: [PATCH 07/16] tests: generate cpu unit tests and skip cuda tests for now --- dev/generate-tests.py | 250 +++++++++++++++++++++++++++++++++--------- 1 file changed, 199 insertions(+), 51 deletions(-) diff --git a/dev/generate-tests.py b/dev/generate-tests.py index 3a97eba6f4..23ccd4f25b 100644 --- a/dev/generate-tests.py +++ b/dev/generate-tests.py @@ -203,6 +203,35 @@ def readspec(): return specdict +def getdtypes(args): + dtypes = [] + for arg in args: + typename = remove_const(arg.typename) + if "List" in typename: + count = typename.count("List") + typename = gettypename(typename) + if typename == "bool" or typename == "float": + typename = typename + "_" + if count == 1: + dtypes.append("cupy." + typename) + return dtypes + + +def checkuint(inputs, args): + flag = True + for arg, val in inputs: + typename = remove_const( + next( + argument + for argument in args + if argument.name == arg + ).typename + ) + if "List[uint" in typename and (any(n < 0 for n in val)): + flag = False + return flag + + def gettypename(spectype): typename = spectype.replace("List", "").replace("[", "").replace("]", "") if typename.endswith("_t"): @@ -460,6 +489,142 @@ def gencpukerneltests(specdict): f.write("\n") +def gencpuunittests(specdict): + print("Generating Unit Tests for CPU kernels") + + unit_tests = unittestmap() + unit_tests_cuda_kernels = os.path.join( + CURRENT_DIR, "..", "awkward-cpp", "tests-cpu-kernels-explicit" + ) + if os.path.exists(unit_tests_cuda_kernels): + shutil.rmtree(unit_tests_cuda_kernels) + os.mkdir(unit_tests_cuda_kernels) + with open(os.path.join(unit_tests_cuda_kernels, "__init__.py"), "w") as f: + f.write( + f"""# AUTO GENERATED ON {reproducible_datetime()} +# DO NOT EDIT BY HAND! +# +# To regenerate file, run +# +# python dev/generate-tests.py +# + +# fmt: off + +""" + ) + + for spec in specdict.values(): + if ( + spec.templatized_kernel_name in list(unit_tests.keys()) + ): + func = "test_cpu" + spec.name + ".py" + num = 0 + with open( + os.path.join(unit_tests_cuda_kernels, func), + "w" + ) as f: + f.write( + f"""# AUTO GENERATED ON {reproducible_datetime()} +# DO NOT EDIT BY HAND! +# +# To regenerate file, run +# +# python dev/generate-tests.py +# + +# fmt: off + +""" + ) + + f.write( + "import ctypes\n" + "import pytest\n\n" + "from awkward_cpp.cpu_kernels import lib\n\n" + ) + unit_test_values = unit_tests[spec.templatized_kernel_name] + tests = unit_test_values["tests"] + for test in tests: + num += 1 + funcName = "def test_" + spec.name + "_" + str(num) + "():\n" + flag = checkuint(test["inputs"].items(), spec.args) + if flag is True: + f.write(funcName) + for arg, val in test["outputs"].items(): + f.write(" " * 4 + arg + " = " + str(val) + "\n") + typename = remove_const( + next( + argument + for argument in spec.args + if argument.name == arg + ).typename + ) + if "List" in typename: + count = typename.count("List") + typename = gettypename(typename) + if count == 1: + f.write( + " " * 4 + + f"{arg} = (ctypes.c_{typename}*len({arg}))(*{arg})\n" + ) + elif count == 2: + f.write( + " " * 4 + + "{0} = ctypes.pointer(ctypes.cast((ctypes.c_{1}*len({0}[0]))(*{0}[0]),ctypes.POINTER(ctypes.c_{1})))\n".format( + arg, typename + ) + ) + for arg, val in test["inputs"].items(): + f.write(" " * 4 + arg + " = " + str(val) + "\n") + typename = remove_const( + next( + argument + for argument in spec.args + if argument.name == arg + ).typename + ) + if "List" in typename: + count = typename.count("List") + typename = gettypename(typename) + if count == 1: + f.write( + " " * 4 + + f"{arg} = (ctypes.c_{typename}*len({arg}))(*{arg})\n" + ) + elif count == 2: + f.write( + " " * 4 + + "{0} = ctypes.pointer(ctypes.cast((ctypes.c_{1}*len({0}[0]))(*{0}[0]),ctypes.POINTER(ctypes.c_{1})))\n".format( + arg, typename + ) + ) + + f.write(" " * 4 + "funcC = getattr(lib, '" + spec.name + "')\n") + args = "" + count = 0 + for arg in spec.args: + if count == 0: + args += arg.name + count += 1 + else: + args += ", " + arg.name + f.write(" " * 4 + "ret_pass = funcC(" + args + ")\n") + for arg, val in test["outputs"].items(): + f.write( + " " * 4 + "pytest_" + arg + " = " + str(val) + "\n" + ) + if isinstance(val, list): + f.write( + " " * 4 + + f"assert {arg}[:len(pytest_{arg})] == pytest.approx(pytest_{arg})\n" + ) + else: + f.write(" " * 4 + f"assert {arg} == pytest_{arg}\n") + f.write(" " * 4 + "assert not ret_pass.str\n") + f.write("\n") + + cuda_kernels_tests = [ "awkward_ListArray_validity", "awkward_BitMaskedArray_to_ByteMaskedArray", @@ -659,19 +824,21 @@ def gencudakerneltests(specdict): f.write("\n") -def cudaunittestmap(): +def unittestmap(): with open(os.path.join(CURRENT_DIR, "..", "kernel-test-data.json")) as f: data = json.load(f)["unit-tests"] - cuda_unit_tests_map = {} + unit_tests_map = {} for function in data: - cuda_unit_tests_map[function["name"]] = function["tests"] - return cuda_unit_tests_map + tests = function["tests"] + status = function["status"] + unit_tests_map[function["name"]] = {"tests": tests, "status": status} + return unit_tests_map def gencudaunittests(specdict): print("Generating Unit Tests for CUDA kernels") - cuda_unit_tests = cudaunittestmap() + unit_tests = unittestmap() unit_tests_cuda_kernels = os.path.join( CURRENT_DIR, "..", "tests-cuda-kernels-explicit" ) @@ -696,15 +863,15 @@ def gencudaunittests(specdict): for spec in specdict.values(): if ( spec.templatized_kernel_name in cuda_kernels_tests - and spec.templatized_kernel_name in list(cuda_unit_tests.keys()) + and spec.templatized_kernel_name in list(unit_tests.keys()) ): func = "test_cuda" + spec.name + ".py" num = 0 with open( - os.path.join(CURRENT_DIR, "..", "tests-cuda-kernels-explicit", func), + os.path.join(unit_tests_cuda_kernels, func), "w", - ) as file: - file.write( + ) as f: + f.write( f"""# AUTO GENERATED ON {reproducible_datetime()} # DO NOT EDIT BY HAND! # @@ -718,7 +885,7 @@ def gencudaunittests(specdict): """ ) - file.write( + f.write( "import cupy\n" "import pytest\n\n" "import awkward as ak\n" @@ -726,40 +893,20 @@ def gencudaunittests(specdict): "from awkward._backends.cupy import CupyBackend\n\n" "cupy_backend = CupyBackend.instance()\n\n" ) - for test in cuda_unit_tests[spec.templatized_kernel_name]: + unit_test_values = unit_tests[spec.templatized_kernel_name] + tests = unit_test_values["tests"] + status = unit_test_values["status"] + for test in tests: num += 1 funcName = "def test_" + spec.name + "_" + str(num) + "():\n" - dtypes = [] - for arg in spec.args: - typename = remove_const(arg.typename) - if "List" in typename: - count = typename.count("List") - typename = gettypename(typename) - if typename == "bool" or typename == "float": - typename = typename + "_" - if count == 1: - dtypes.append("cupy." + typename) - flag = True - for arg, val in test["inputs"].items(): - typename = remove_const( - next( - argument - for argument in spec.args - if argument.name == arg - ).typename - ) - if "List[uint" in typename and (any(n < 0 for n in val)): - flag = False - file.write( + dtypes = getdtypes(spec.args) + flag = checkuint(test["inputs"].items(), spec.args) + if flag is True: + if not status: + f.write( "@pytest.mark.skip(reason='Unable to generate any tests for kernel')\n" ) - file.write(funcName) - file.write( - " " * 4 - + "raise NotImplementedError('Unable to generate any tests for kernel')\n\n" - ) - if flag is True: - file.write(funcName) + f.write(funcName) for arg, val in test["outputs"].items(): typename = remove_const( next( @@ -769,7 +916,7 @@ def gencudaunittests(specdict): ).typename ) if "List" not in typename: - file.write( + f.write( " " * 4 + arg + " = " + str([123] * len(val)) + "\n" ) if "List" in typename: @@ -778,7 +925,7 @@ def gencudaunittests(specdict): if typename == "bool" or typename == "float": typename = typename + "_" if count == 1: - file.write( + f.write( " " * 4 + "{} = cupy.array({}, dtype=cupy.{})\n".format( arg, str([123] * len(val)), typename @@ -795,14 +942,14 @@ def gencudaunittests(specdict): ).typename ) if "List" not in typename: - file.write(" " * 4 + arg + " = " + str(val) + "\n") + f.write(" " * 4 + arg + " = " + str(val) + "\n") if "List" in typename: count = typename.count("List") typename = gettypename(typename) if typename == "bool" or typename == "float": typename = typename + "_" if count == 1: - file.write( + f.write( " " * 4 + "{} = cupy.array({}, dtype=cupy.{})\n".format( arg, val, typename @@ -816,7 +963,7 @@ def gencudaunittests(specdict): + spec.templatized_kernel_name + "', {}]\n".format(", ".join(dtypes)) ) - file.write(" " * 4 + cuda_string) + f.write(" " * 4 + cuda_string) args = "" count = 0 for arg in spec.args: @@ -825,8 +972,8 @@ def gencudaunittests(specdict): count += 1 else: args += ", " + arg.name - file.write(" " * 4 + "funcC(" + args + ")\n") - file.write( + f.write(" " * 4 + "funcC(" + args + ")\n") + f.write( """ try: ak_cu.synchronize_cuda() @@ -835,17 +982,17 @@ def gencudaunittests(specdict): """ ) for arg, val in test["outputs"].items(): - file.write( + f.write( " " * 4 + "pytest_" + arg + " = " + str(val) + "\n" ) if isinstance(val, list): - file.write( + f.write( " " * 4 + f"assert cupy.array_equal({arg}[:len(pytest_{arg})], cupy.array(pytest_{arg}))\n" ) else: - file.write(" " * 4 + f"assert {arg} == pytest_{arg}\n") - file.write("\n") + f.write(" " * 4 + f"assert {arg} == pytest_{arg}\n") + f.write("\n") def genunittests(): @@ -902,6 +1049,7 @@ def evalkernels(): specdict = readspec() genspectests(specdict) gencpukerneltests(specdict) + gencpuunittests(specdict) genunittests() gencudakerneltests(specdict) gencudaunittests(specdict) From dbfe8a96018745e95ba63a440cfae0c1bf81137d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 10:58:36 +0000 Subject: [PATCH 08/16] style: pre-commit fixes --- dev/generate-tests.py | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/dev/generate-tests.py b/dev/generate-tests.py index 23ccd4f25b..dd48225f11 100644 --- a/dev/generate-tests.py +++ b/dev/generate-tests.py @@ -221,11 +221,7 @@ def checkuint(inputs, args): flag = True for arg, val in inputs: typename = remove_const( - next( - argument - for argument in args - if argument.name == arg - ).typename + next(argument for argument in args if argument.name == arg).typename ) if "List[uint" in typename and (any(n < 0 for n in val)): flag = False @@ -515,15 +511,10 @@ def gencpuunittests(specdict): ) for spec in specdict.values(): - if ( - spec.templatized_kernel_name in list(unit_tests.keys()) - ): + if spec.templatized_kernel_name in list(unit_tests.keys()): func = "test_cpu" + spec.name + ".py" num = 0 - with open( - os.path.join(unit_tests_cuda_kernels, func), - "w" - ) as f: + with open(os.path.join(unit_tests_cuda_kernels, func), "w") as f: f.write( f"""# AUTO GENERATED ON {reproducible_datetime()} # DO NOT EDIT BY HAND! @@ -608,12 +599,10 @@ def gencpuunittests(specdict): args += arg.name count += 1 else: - args += ", " + arg.name + args += ", " + arg.name f.write(" " * 4 + "ret_pass = funcC(" + args + ")\n") for arg, val in test["outputs"].items(): - f.write( - " " * 4 + "pytest_" + arg + " = " + str(val) + "\n" - ) + f.write(" " * 4 + "pytest_" + arg + " = " + str(val) + "\n") if isinstance(val, list): f.write( " " * 4 @@ -896,7 +885,7 @@ def gencudaunittests(specdict): unit_test_values = unit_tests[spec.templatized_kernel_name] tests = unit_test_values["tests"] status = unit_test_values["status"] - for test in tests: + for test in tests: num += 1 funcName = "def test_" + spec.name + "_" + str(num) + "():\n" dtypes = getdtypes(spec.args) @@ -982,9 +971,7 @@ def gencudaunittests(specdict): """ ) for arg, val in test["outputs"].items(): - f.write( - " " * 4 + "pytest_" + arg + " = " + str(val) + "\n" - ) + f.write(" " * 4 + "pytest_" + arg + " = " + str(val) + "\n") if isinstance(val, list): f.write( " " * 4 From 76f505d3a065d466f839d2762b943f66d6f792f2 Mon Sep 17 00:00:00 2001 From: ManasviGoyal Date: Thu, 18 Jan 2024 17:26:05 +0100 Subject: [PATCH 09/16] tests: remove out of bound tests --- dev/generate-tests.py | 132 ++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 77 deletions(-) diff --git a/dev/generate-tests.py b/dev/generate-tests.py index dd48225f11..da5899719e 100644 --- a/dev/generate-tests.py +++ b/dev/generate-tests.py @@ -12,6 +12,7 @@ from itertools import product import yaml +import numpy as np from numpy import uint8 # noqa: F401 (used in evaluated strings) CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) @@ -210,16 +211,14 @@ def getdtypes(args): if "List" in typename: count = typename.count("List") typename = gettypename(typename) - if typename == "bool" or typename == "float": - typename = typename + "_" if count == 1: dtypes.append("cupy." + typename) return dtypes -def checkuint(inputs, args): +def checkuint(test_args, args): flag = True - for arg, val in inputs: + for arg, val in test_args: typename = remove_const( next(argument for argument in args if argument.name == arg).typename ) @@ -227,6 +226,40 @@ def checkuint(inputs, args): flag = False return flag +def checkintrange(test_args, args): + flag = True + for arg, val in test_args: + typename = remove_const( + next(argument for argument in args if argument.name == arg).typename + ) + if "int" in typename or "uint" in typename: + dtype = gettypename(typename) + min_val, max_val = np.iinfo(dtype).min, np.iinfo(dtype).max + if "List" in typename: + for data in val: + if not (min_val <= data <= max_val): + flag = False + else: + if not (min_val <= val <= max_val): + flag = False + return flag + + +def unittestmap(): + with open(os.path.join(CURRENT_DIR, "..", "kernel-test-data.json")) as f: + data = json.load(f)["unit-tests"] + unit_tests_map = {} + for function in data: + tests = function["tests"] + status = function["status"] + unit_tests_map[function["name"]] = {"tests": tests, "status": status} + return unit_tests_map + + +def getunittests(test_inputs, test_outputs): + unit_tests = {**test_inputs, **test_outputs} + return unit_tests + def gettypename(spectype): typename = spectype.replace("List", "").replace("[", "").replace("]", "") @@ -488,7 +521,7 @@ def gencpukerneltests(specdict): def gencpuunittests(specdict): print("Generating Unit Tests for CPU kernels") - unit_tests = unittestmap() + unit_test_map = unittestmap() unit_tests_cuda_kernels = os.path.join( CURRENT_DIR, "..", "awkward-cpp", "tests-cpu-kernels-explicit" ) @@ -511,7 +544,7 @@ def gencpuunittests(specdict): ) for spec in specdict.values(): - if spec.templatized_kernel_name in list(unit_tests.keys()): + if spec.templatized_kernel_name in list(unit_test_map.keys()): func = "test_cpu" + spec.name + ".py" num = 0 with open(os.path.join(unit_tests_cuda_kernels, func), "w") as f: @@ -534,39 +567,17 @@ def gencpuunittests(specdict): "import pytest\n\n" "from awkward_cpp.cpu_kernels import lib\n\n" ) - unit_test_values = unit_tests[spec.templatized_kernel_name] + unit_test_values = unit_test_map[spec.templatized_kernel_name] tests = unit_test_values["tests"] for test in tests: num += 1 funcName = "def test_" + spec.name + "_" + str(num) + "():\n" - flag = checkuint(test["inputs"].items(), spec.args) - if flag is True: + unit_tests = getunittests(test["inputs"], test["outputs"]) + flag = checkuint(unit_tests.items(), spec.args) + range = checkintrange(unit_tests.items(), spec.args) + if flag and range: f.write(funcName) - for arg, val in test["outputs"].items(): - f.write(" " * 4 + arg + " = " + str(val) + "\n") - typename = remove_const( - next( - argument - for argument in spec.args - if argument.name == arg - ).typename - ) - if "List" in typename: - count = typename.count("List") - typename = gettypename(typename) - if count == 1: - f.write( - " " * 4 - + f"{arg} = (ctypes.c_{typename}*len({arg}))(*{arg})\n" - ) - elif count == 2: - f.write( - " " * 4 - + "{0} = ctypes.pointer(ctypes.cast((ctypes.c_{1}*len({0}[0]))(*{0}[0]),ctypes.POINTER(ctypes.c_{1})))\n".format( - arg, typename - ) - ) - for arg, val in test["inputs"].items(): + for arg, val in unit_tests.items(): f.write(" " * 4 + arg + " = " + str(val) + "\n") typename = remove_const( next( @@ -813,21 +824,10 @@ def gencudakerneltests(specdict): f.write("\n") -def unittestmap(): - with open(os.path.join(CURRENT_DIR, "..", "kernel-test-data.json")) as f: - data = json.load(f)["unit-tests"] - unit_tests_map = {} - for function in data: - tests = function["tests"] - status = function["status"] - unit_tests_map[function["name"]] = {"tests": tests, "status": status} - return unit_tests_map - - def gencudaunittests(specdict): print("Generating Unit Tests for CUDA kernels") - unit_tests = unittestmap() + unit_test_map = unittestmap() unit_tests_cuda_kernels = os.path.join( CURRENT_DIR, "..", "tests-cuda-kernels-explicit" ) @@ -852,7 +852,7 @@ def gencudaunittests(specdict): for spec in specdict.values(): if ( spec.templatized_kernel_name in cuda_kernels_tests - and spec.templatized_kernel_name in list(unit_tests.keys()) + and spec.templatized_kernel_name in list(unit_test_map.keys()) ): func = "test_cuda" + spec.name + ".py" num = 0 @@ -882,21 +882,23 @@ def gencudaunittests(specdict): "from awkward._backends.cupy import CupyBackend\n\n" "cupy_backend = CupyBackend.instance()\n\n" ) - unit_test_values = unit_tests[spec.templatized_kernel_name] + unit_test_values = unit_test_map[spec.templatized_kernel_name] tests = unit_test_values["tests"] status = unit_test_values["status"] for test in tests: num += 1 funcName = "def test_" + spec.name + "_" + str(num) + "():\n" dtypes = getdtypes(spec.args) - flag = checkuint(test["inputs"].items(), spec.args) - if flag is True: + unit_tests = getunittests(test["inputs"], test["outputs"]) + flag = checkuint(unit_tests.items(), spec.args) + range = checkintrange(unit_tests.items(), spec.args) + if flag and range: if not status: f.write( - "@pytest.mark.skip(reason='Unable to generate any tests for kernel')\n" + "@pytest.mark.skip(reason='Kernel is not implemented properly')\n" ) f.write(funcName) - for arg, val in test["outputs"].items(): + for arg, val in unit_tests.items(): typename = remove_const( next( argument @@ -906,32 +908,8 @@ def gencudaunittests(specdict): ) if "List" not in typename: f.write( - " " * 4 + arg + " = " + str([123] * len(val)) + "\n" + " " * 4 + arg + " = " + str(val) + "\n" ) - if "List" in typename: - count = typename.count("List") - typename = gettypename(typename) - if typename == "bool" or typename == "float": - typename = typename + "_" - if count == 1: - f.write( - " " * 4 - + "{} = cupy.array({}, dtype=cupy.{})\n".format( - arg, str([123] * len(val)), typename - ) - ) - elif count == 2: - raise NotImplementedError - for arg, val in test["inputs"].items(): - typename = remove_const( - next( - argument - for argument in spec.args - if argument.name == arg - ).typename - ) - if "List" not in typename: - f.write(" " * 4 + arg + " = " + str(val) + "\n") if "List" in typename: count = typename.count("List") typename = gettypename(typename) From bd0515c3649e502d0eebdf745bdd0c099685fe6a Mon Sep 17 00:00:00 2001 From: ManasviGoyal Date: Fri, 19 Jan 2024 10:04:53 +0100 Subject: [PATCH 10/16] fix: output values --- dev/generate-tests.py | 67 +++++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/dev/generate-tests.py b/dev/generate-tests.py index da5899719e..93363aff3c 100644 --- a/dev/generate-tests.py +++ b/dev/generate-tests.py @@ -11,8 +11,8 @@ from collections import OrderedDict from itertools import product -import yaml import numpy as np +import yaml from numpy import uint8 # noqa: F401 (used in evaluated strings) CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) @@ -226,6 +226,7 @@ def checkuint(test_args, args): flag = False return flag + def checkintrange(test_args, args): flag = True for arg, val in test_args: @@ -257,8 +258,9 @@ def unittestmap(): def getunittests(test_inputs, test_outputs): - unit_tests = {**test_inputs, **test_outputs} - return unit_tests + unit_tests = {**test_outputs, **test_inputs} + num_outputs = len(test_outputs) + return unit_tests, num_outputs def gettypename(spectype): @@ -546,7 +548,7 @@ def gencpuunittests(specdict): for spec in specdict.values(): if spec.templatized_kernel_name in list(unit_test_map.keys()): func = "test_cpu" + spec.name + ".py" - num = 0 + num = 1 with open(os.path.join(unit_tests_cuda_kernels, func), "w") as f: f.write( f"""# AUTO GENERATED ON {reproducible_datetime()} @@ -570,15 +572,16 @@ def gencpuunittests(specdict): unit_test_values = unit_test_map[spec.templatized_kernel_name] tests = unit_test_values["tests"] for test in tests: - num += 1 funcName = "def test_" + spec.name + "_" + str(num) + "():\n" - unit_tests = getunittests(test["inputs"], test["outputs"]) + unit_tests, num_outputs = getunittests( + test["inputs"], test["outputs"] + ) flag = checkuint(unit_tests.items(), spec.args) range = checkintrange(unit_tests.items(), spec.args) if flag and range: + num += 1 f.write(funcName) - for arg, val in unit_tests.items(): - f.write(" " * 4 + arg + " = " + str(val) + "\n") + for i, (arg, val) in enumerate(unit_tests.items()): typename = remove_const( next( argument @@ -586,6 +589,16 @@ def gencpuunittests(specdict): if argument.name == arg ).typename ) + if i < num_outputs: + f.write( + " " * 4 + + arg + + " = " + + str([gettypeval(typename)] * len(val)) + + "\n" + ) + else: + f.write(" " * 4 + arg + " = " + str(val) + "\n") if "List" in typename: count = typename.count("List") typename = gettypename(typename) @@ -622,7 +635,7 @@ def gencpuunittests(specdict): else: f.write(" " * 4 + f"assert {arg} == pytest_{arg}\n") f.write(" " * 4 + "assert not ret_pass.str\n") - f.write("\n") + f.write("\n") cuda_kernels_tests = [ @@ -855,7 +868,7 @@ def gencudaunittests(specdict): and spec.templatized_kernel_name in list(unit_test_map.keys()) ): func = "test_cuda" + spec.name + ".py" - num = 0 + num = 1 with open( os.path.join(unit_tests_cuda_kernels, func), "w", @@ -886,19 +899,21 @@ def gencudaunittests(specdict): tests = unit_test_values["tests"] status = unit_test_values["status"] for test in tests: - num += 1 funcName = "def test_" + spec.name + "_" + str(num) + "():\n" dtypes = getdtypes(spec.args) - unit_tests = getunittests(test["inputs"], test["outputs"]) + unit_tests, num_outputs = getunittests( + test["inputs"], test["outputs"] + ) flag = checkuint(unit_tests.items(), spec.args) range = checkintrange(unit_tests.items(), spec.args) if flag and range: + num += 1 if not status: f.write( "@pytest.mark.skip(reason='Kernel is not implemented properly')\n" ) f.write(funcName) - for arg, val in unit_tests.items(): + for i, (arg, val) in enumerate(unit_tests.items()): typename = remove_const( next( argument @@ -907,21 +922,29 @@ def gencudaunittests(specdict): ).typename ) if "List" not in typename: - f.write( - " " * 4 + arg + " = " + str(val) + "\n" - ) + f.write(" " * 4 + arg + " = " + str(val) + "\n") if "List" in typename: count = typename.count("List") typename = gettypename(typename) if typename == "bool" or typename == "float": typename = typename + "_" if count == 1: - f.write( - " " * 4 - + "{} = cupy.array({}, dtype=cupy.{})\n".format( - arg, val, typename + if i < num_outputs: + f.write( + " " * 4 + + "{} = cupy.array({}, dtype=cupy.{})\n".format( + arg, + [gettypeval(typename)] * len(val), + typename, + ) + ) + else: + f.write( + " " * 4 + + "{} = cupy.array({}, dtype=cupy.{})\n".format( + arg, val, typename + ) ) - ) elif count == 2: raise NotImplementedError @@ -957,7 +980,7 @@ def gencudaunittests(specdict): ) else: f.write(" " * 4 + f"assert {arg} == pytest_{arg}\n") - f.write("\n") + f.write("\n") def genunittests(): From 20e90bfa2ad4865b7b4d8736e30a3145e51b4178 Mon Sep 17 00:00:00 2001 From: ManasviGoyal Date: Fri, 19 Jan 2024 10:19:33 +0100 Subject: [PATCH 11/16] ci: add tests-cpu-kernels-explicit --- .github/workflows/test.yml | 3 +++ awkward-cpp/.gitignore | 1 + awkward-cpp/pyproject.toml | 3 ++- cibuildwheel.toml | 1 + noxfile.py | 1 + 5 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4ad4324838..6c597fe0a8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -124,6 +124,9 @@ jobs: - name: Test CPU kernels run: python -m pytest -vv -rs awkward-cpp/tests-cpu-kernels + - name: Test CPU kernels with explicitly defined values + run: python -m pytest -vv -rs awkward-cpp/tests-cpu-kernels-explicit + - name: Test non-kernels run: >- python -m pytest -vv -rs tests --cov=awkward --cov-report=term diff --git a/awkward-cpp/.gitignore b/awkward-cpp/.gitignore index b0d2907f4c..d8cc882e48 100644 --- a/awkward-cpp/.gitignore +++ b/awkward-cpp/.gitignore @@ -11,5 +11,6 @@ src/awkward_cpp/_kernel_signatures.py tests-spec tests-spec-explicit tests-cpu-kernels +tests-cpu-kernels-explicit dist diff --git a/awkward-cpp/pyproject.toml b/awkward-cpp/pyproject.toml index 6fb36b3387..6f306c740a 100644 --- a/awkward-cpp/pyproject.toml +++ b/awkward-cpp/pyproject.toml @@ -68,5 +68,6 @@ sdist.include = [ "src/awkward_cpp/_kernel_signatures.py", "tests-spec", "tests-spec-explicit", - "tests-cpu-kernels" + "tests-cpu-kernels", + "tests-cpu-kernels-explicit" ] diff --git a/cibuildwheel.toml b/cibuildwheel.toml index bfca433578..372b80f5ab 100644 --- a/cibuildwheel.toml +++ b/cibuildwheel.toml @@ -3,6 +3,7 @@ test-requires = ["pytest>=6", "."] test-command = """ pytest {project}/tests \ {package}/tests-cpu-kernels \ + {package}/tests-cpu-kernels-explicit \ {package}/tests-spec \ {package}/tests-spec-explicit """ diff --git a/noxfile.py b/noxfile.py index 61eb0566e7..a4fc7f5e4a 100644 --- a/noxfile.py +++ b/noxfile.py @@ -132,6 +132,7 @@ def clean(session): pathlib.Path("awkward-cpp", "tests-spec"), pathlib.Path("awkward-cpp", "tests-spec-explicit"), pathlib.Path("awkward-cpp", "tests-cpu-kernels"), + pathlib.Path("awkward-cpp", "tests-cpu-kernels-explicit"), pathlib.Path("tests-cuda-kernels"), ) if args.docs or clean_all: From 82ed05f103ef598a456b6dd611beb302444fcca1 Mon Sep 17 00:00:00 2001 From: ManasviGoyal Date: Fri, 19 Jan 2024 10:49:48 +0100 Subject: [PATCH 12/16] refactor: change name of tests --- dev/generate-tests.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/dev/generate-tests.py b/dev/generate-tests.py index 93363aff3c..879a7d8331 100644 --- a/dev/generate-tests.py +++ b/dev/generate-tests.py @@ -547,7 +547,7 @@ def gencpuunittests(specdict): for spec in specdict.values(): if spec.templatized_kernel_name in list(unit_test_map.keys()): - func = "test_cpu" + spec.name + ".py" + func = "test_unit_cpu" + spec.name + ".py" num = 1 with open(os.path.join(unit_tests_cuda_kernels, func), "w") as f: f.write( @@ -572,7 +572,9 @@ def gencpuunittests(specdict): unit_test_values = unit_test_map[spec.templatized_kernel_name] tests = unit_test_values["tests"] for test in tests: - funcName = "def test_" + spec.name + "_" + str(num) + "():\n" + funcName = ( + "def test_unit_cpu" + spec.name + "_" + str(num) + "():\n" + ) unit_tests, num_outputs = getunittests( test["inputs"], test["outputs"] ) @@ -867,7 +869,7 @@ def gencudaunittests(specdict): spec.templatized_kernel_name in cuda_kernels_tests and spec.templatized_kernel_name in list(unit_test_map.keys()) ): - func = "test_cuda" + spec.name + ".py" + func = "test_unit_cuda" + spec.name + ".py" num = 1 with open( os.path.join(unit_tests_cuda_kernels, func), @@ -899,7 +901,9 @@ def gencudaunittests(specdict): tests = unit_test_values["tests"] status = unit_test_values["status"] for test in tests: - funcName = "def test_" + spec.name + "_" + str(num) + "():\n" + funcName = ( + "def test_unit_cuda" + spec.name + "_" + str(num) + "():\n" + ) dtypes = getdtypes(spec.args) unit_tests, num_outputs = getunittests( test["inputs"], test["outputs"] From 3c008a8497181296b036847d07d8202eec34a520 Mon Sep 17 00:00:00 2001 From: ManasviGoyal Date: Fri, 19 Jan 2024 13:34:23 +0100 Subject: [PATCH 13/16] fix: CuPy dtype --- dev/generate-tests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dev/generate-tests.py b/dev/generate-tests.py index 879a7d8331..1d63144001 100644 --- a/dev/generate-tests.py +++ b/dev/generate-tests.py @@ -211,6 +211,8 @@ def getdtypes(args): if "List" in typename: count = typename.count("List") typename = gettypename(typename) + if typename == "bool" or typename == "float": + typename = typename + "_" if count == 1: dtypes.append("cupy." + typename) return dtypes From 5584e32397dbda37e3ce0d96a879c6fc416e89ad Mon Sep 17 00:00:00 2001 From: ManasviGoyal Date: Fri, 19 Jan 2024 13:43:46 +0100 Subject: [PATCH 14/16] refactor: correct variable name --- dev/generate-tests.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dev/generate-tests.py b/dev/generate-tests.py index 1d63144001..ff42a5293a 100644 --- a/dev/generate-tests.py +++ b/dev/generate-tests.py @@ -526,13 +526,13 @@ def gencpuunittests(specdict): print("Generating Unit Tests for CPU kernels") unit_test_map = unittestmap() - unit_tests_cuda_kernels = os.path.join( + unit_tests_cpu_kernels = os.path.join( CURRENT_DIR, "..", "awkward-cpp", "tests-cpu-kernels-explicit" ) - if os.path.exists(unit_tests_cuda_kernels): - shutil.rmtree(unit_tests_cuda_kernels) - os.mkdir(unit_tests_cuda_kernels) - with open(os.path.join(unit_tests_cuda_kernels, "__init__.py"), "w") as f: + if os.path.exists(unit_tests_cpu_kernels): + shutil.rmtree(unit_tests_cpu_kernels) + os.mkdir(unit_tests_cpu_kernels) + with open(os.path.join(unit_tests_cpu_kernels, "__init__.py"), "w") as f: f.write( f"""# AUTO GENERATED ON {reproducible_datetime()} # DO NOT EDIT BY HAND! @@ -551,7 +551,7 @@ def gencpuunittests(specdict): if spec.templatized_kernel_name in list(unit_test_map.keys()): func = "test_unit_cpu" + spec.name + ".py" num = 1 - with open(os.path.join(unit_tests_cuda_kernels, func), "w") as f: + with open(os.path.join(unit_tests_cpu_kernels, func), "w") as f: f.write( f"""# AUTO GENERATED ON {reproducible_datetime()} # DO NOT EDIT BY HAND! From 411d40f80523c653b1e576fa9e43df6c7c0504c8 Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Fri, 19 Jan 2024 11:11:13 -0600 Subject: [PATCH 15/16] don't track auto-generated tests in git --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index 69ad888f5f..d28e4e3ea8 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,12 @@ src/awkward/_connect/header-only src/awkward/_version.py # Kernel tests +awkward-cpp/tests-cpu-kernels +awkward-cpp/tests-cpu-kernels-explicit +awkward-cpp/tests-spec +awkward-cpp/tests-spec-explicit tests-cuda-kernels +tests-cuda-kernels-explicit # to use all-contributors-cli without adding it to the project node_modules From 27af67a14df8edf37a03578c1a5064818acc6994 Mon Sep 17 00:00:00 2001 From: Manasvi Goyal <55101825+ManasviGoyal@users.noreply.github.com> Date: Fri, 19 Jan 2024 19:54:15 +0100 Subject: [PATCH 16/16] refactor: remove kernel tests from awkward-cpp .gitignore --- awkward-cpp/.gitignore | 6 ------ 1 file changed, 6 deletions(-) diff --git a/awkward-cpp/.gitignore b/awkward-cpp/.gitignore index d8cc882e48..6ba1c8061e 100644 --- a/awkward-cpp/.gitignore +++ b/awkward-cpp/.gitignore @@ -7,10 +7,4 @@ header-only include/awkward/kernels.h src/awkward_cpp/_kernel_signatures.py -# Kernel tests -tests-spec -tests-spec-explicit -tests-cpu-kernels -tests-cpu-kernels-explicit - dist