Skip to content

Commit

Permalink
Merge pull request KhronosGroup#927 from steffenlarsen/steffen/split_…
Browse files Browse the repository at this point in the history
…math_builtin_tests

Change math_builtin_api generator to split generated sources
  • Loading branch information
steffenlarsen authored Sep 11, 2024
2 parents db26da8 + b43a573 commit eecbab4
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 63 deletions.
60 changes: 60 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,66 @@ function(generate_cts_test)
add_dependencies(generate_test_sources ${GEN_TEST_FILE_NAME}_gen)
endfunction()

# Test generation routine
function(generate_multifile_cts_test)
cmake_parse_arguments(
GEN_TEST
""
"TESTS;GENERATOR;FILE_PREFIX;EXT;INPUT"
"EXTRA_ARGS;DEPENDS"
${ARGN}
)
get_filename_component(test_dir ${CMAKE_CURRENT_SOURCE_DIR} NAME)
if(${test_dir} IN_LIST exclude_categories)
return()
endif()

message(STATUS "Setup test generation rules for prefix: " ${GEN_TEST_FILE_PREFIX})

set(GEN_TEST_INPUT ${CMAKE_CURRENT_SOURCE_DIR}/${GEN_TEST_INPUT})

# Execute generator to get the files that will be generated.
execute_process(COMMAND
${PYTHON_EXECUTABLE}
${GEN_TEST_GENERATOR}
${GEN_TEST_INPUT}
-output-prefix ${CMAKE_CURRENT_BINARY_DIR}/${GEN_TEST_FILE_PREFIX}
-ext ${GEN_TEST_EXT}
-print-output-files
${GEN_TEST_EXTRA_ARGS}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GEN_TEST_OUTPUT_FILES
OUTPUT_STRIP_TRAILING_WHITESPACE
ECHO_ERROR_VARIABLE)

# Add the file to the out test list
set(${GEN_TEST_TESTS} ${${GEN_TEST_TESTS}} ${GEN_TEST_OUTPUT_FILES} PARENT_SCOPE)

set(extra_deps "")
foreach(filename ${GEN_TEST_DEPENDS})
list(APPEND extra_deps ${CMAKE_CURRENT_SOURCE_DIR}/${filename})
endforeach()

add_custom_command(OUTPUT ${GEN_TEST_OUTPUT_FILES}
COMMAND
${PYTHON_EXECUTABLE}
${GEN_TEST_GENERATOR}
${GEN_TEST_INPUT}
-output-prefix ${CMAKE_CURRENT_BINARY_DIR}/${GEN_TEST_FILE_PREFIX}
-ext ${GEN_TEST_EXT}
${GEN_TEST_EXTRA_ARGS}
DEPENDS
${GEN_TEST_GENERATOR}
${GEN_TEST_INPUT}
${extra_deps}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Generating test ${GEN_TEST_FILE_PREFIX}..."
)

add_custom_target(${GEN_TEST_FILE_PREFIX}_gen DEPENDS ${GEN_TEST_OUTPUT_FILES})
add_dependencies(generate_test_sources ${GEN_TEST_FILE_PREFIX}_gen)
endfunction()

# create a target to encapsulate all test categories.
add_custom_target(test_conformance)

Expand Down
14 changes: 8 additions & 6 deletions tests/math_builtin_api/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ foreach(cat ${MATH_CAT_WITH_VARIANT})
endif()
# Invoke our generator
# the path to the generated cpp file will be added to TEST_CASES_LIST
generate_cts_test(TESTS TEST_CASES_LIST
generate_multifile_cts_test(TESTS TEST_CASES_LIST
GENERATOR "generate_math_builtin.py"
OUTPUT "math_builtin_${cat}_${var}.cpp"
FILE_PREFIX "math_builtin_${cat}_${var}"
EXT "cpp"
INPUT "math_builtin.template"
EXTRA_ARGS -test ${cat} -variante ${var} -marray true
EXTRA_ARGS -test ${cat} -variante ${var} -marray true -fragment-size 150
DEPENDS ${math_builtin_depends}
)
endforeach()
Expand All @@ -38,11 +39,12 @@ endforeach()
foreach(cat ${MATH_CAT})
# Invoke our generator
# the path to the generated cpp file will be added to TEST_CASES_LIST
generate_cts_test(TESTS TEST_CASES_LIST
generate_multifile_cts_test(TESTS TEST_CASES_LIST
GENERATOR "generate_math_builtin.py"
OUTPUT "math_builtin_${cat}.cpp"
FILE_PREFIX "math_builtin_${cat}"
EXT "cpp"
INPUT "math_builtin.template"
EXTRA_ARGS -test ${cat} -marray true
EXTRA_ARGS -test ${cat} -marray true -fragment-size 150
DEPENDS ${math_builtin_depends}
)
endforeach()
Expand Down
141 changes: 88 additions & 53 deletions tests/math_builtin_api/generate_math_builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import os
import sys
import argparse
import math
from modules import sycl_types
from modules import sycl_functions
from modules import test_generator
Expand Down Expand Up @@ -74,34 +75,9 @@ def write_cases_to_file(generated_test_cases, inputFile, outputFile, extension=N
with open(outputFile, 'w+') as output:
output.write(newSource)

def create_tests(test_id, types, signatures, kind, template, file_name, check = False):
expanded_signatures = test_generator.expand_signatures(types, signatures)

# Extensions should be placed on separate files.
base_signatures = []
half_signatures = []
double_signatures = []
for sig in expanded_signatures:
if contains_base_type(sig, "double"):
double_signatures.append(sig)
continue
if contains_base_type(sig, "sycl::half"):
half_signatures.append(sig)
continue
base_signatures.append(sig)

if base_signatures and kind == 'base':
generated_base_test_cases = test_generator.generate_test_cases(test_id, types, base_signatures, check)
write_cases_to_file(generated_base_test_cases, template, file_name)
elif half_signatures and kind == 'half':
generated_half_test_cases = test_generator.generate_test_cases(test_id + 300000, types, half_signatures, check)
write_cases_to_file(generated_half_test_cases, template, file_name, "fp16")
elif double_signatures and kind == 'double':
generated_double_test_cases = test_generator.generate_test_cases(test_id + 600000, types, double_signatures, check)
write_cases_to_file(generated_double_test_cases, template, file_name, "fp64")
else:
print("No %s overloads to generate for the test category" % kind)
sys.exit(1)
def create_tests(test_id, types, signatures, template, file_name, extension, check = False):
generated_test_cases = test_generator.generate_test_cases(test_id, types, signatures, check)
write_cases_to_file(generated_test_cases, template, file_name, extension)

def main():
argparser = argparse.ArgumentParser(
Expand All @@ -127,11 +103,22 @@ def main():
default='false',
help='Generate tests with marray function arguments')
argparser.add_argument(
'-o',
dest="output",
'-print-output-files',
action='store_true',
help='Print all generated output files instead of generating the test files')
argparser.add_argument(
'-fragment-size',
type=int,
required=False,
help='Generate test files with tests for N math function signatures')
argparser.add_argument(
'-output-prefix',
required=True,
metavar='<out file>',
help='CTS test output')
help='CTS test output file name prefix')
argparser.add_argument(
'-ext',
required=True,
help='CTS test output file extension')
args = argparser.parse_args()

use_marray = (args.marray == 'true')
Expand All @@ -145,33 +132,81 @@ def main():

verifyResults = True

test_signatures = []
test_id_offset = 0
if args.test == 'integer':
integer_signatures = sycl_functions.create_integer_signatures()
create_tests(0, expanded_types, integer_signatures, args.variante, args.template, args.output, verifyResults)

if args.test == 'common':
common_signatures = sycl_functions.create_common_signatures()
create_tests(1000000, expanded_types, common_signatures, args.variante, args.template, args.output, verifyResults)
test_signatures = sycl_functions.create_integer_signatures()
test_id_offset = 0
elif args.test == 'common':
test_signatures = sycl_functions.create_common_signatures()
test_id_offset = 1000000
elif args.test == 'geometric':
test_signatures = sycl_functions.create_geometric_signatures()
test_id_offset = 2000000
elif args.test == 'relational':
test_signatures = sycl_functions.create_relational_signatures()
test_id_offset = 3000000
elif args.test == 'float':
test_signatures = sycl_functions.create_float_signatures()
test_id_offset = 4000000
elif args.test == 'native':
test_signatures = sycl_functions.create_native_signatures()
test_id_offset = 5000000
elif args.test == 'half':
test_signatures = sycl_functions.create_half_signatures()
test_id_offset = 6000000

test_signatures = test_generator.expand_signatures(expanded_types, test_signatures, silent=args.print_output_files)

if args.test == 'geometric':
geomteric_signatures = sycl_functions.create_geometric_signatures()
create_tests(2000000, expanded_types, geomteric_signatures, args.variante, args.template, args.output, verifyResults)
# Extensions should be placed on separate files.
base_signatures = []
half_signatures = []
double_signatures = []
for sig in test_signatures:
if contains_base_type(sig, "double"):
double_signatures.append(sig)
continue
if contains_base_type(sig, "sycl::half"):
half_signatures.append(sig)
continue
base_signatures.append(sig)

if args.test == 'relational':
relational_signatures = sycl_functions.create_relational_signatures()
create_tests(3000000, expanded_types, relational_signatures, args.variante, args.template, args.output, verifyResults)
# Update signatures based on the variants
extension = None
if base_signatures and args.variante == 'base':
test_signatures = base_signatures
elif half_signatures and args.variante == 'half':
test_signatures = half_signatures
test_id_offset = test_id_offset + 300000
extension = "fp16"
elif double_signatures and args.variante == 'double':
test_signatures = double_signatures
test_id_offset = test_id_offset + 600000
extension = "fp64"
else:
print("No %s overloads to generate for the test category" % args.variante)
sys.exit(1)

if args.test == 'float':
float_signatures = sycl_functions.create_float_signatures()
create_tests(4000000, expanded_types, float_signatures, args.variante, args.template, args.output, verifyResults)
output_files = []
if len(test_signatures) != 0:
if not args.fragment_size:
output_files = [args.output_prefix + "." + args.ext]
else:
output_files = [args.output_prefix + "_" + str(i) + "." + args.ext for i in range(0, math.ceil(len(test_signatures) / args.fragment_size))]

if args.test == 'native':
native_signatures = sycl_functions.create_native_signatures()
create_tests(5000000, expanded_types, native_signatures, args.variante, args.template, args.output, verifyResults)
if args.print_output_files:
print(';'.join(output_files))
# If output files are being printed we will not generate files.
return

if args.test == 'half':
half_signatures = sycl_functions.create_half_signatures()
create_tests(6000000, expanded_types, half_signatures, args.variante, args.template, args.output, verifyResults)
if not args.fragment_size:
create_tests(test_id_offset, expanded_types, test_signatures, args.variante, args.template, output_files[0], extension, verifyResults)
else:
for i in range(0, math.ceil(len(test_signatures) / args.fragment_size)):
fragment_start = i * args.fragment_size
fragment_end = fragment_start + args.fragment_size
current_offset = test_id_offset + fragment_start * 100
create_tests(current_offset, expanded_types, test_signatures[fragment_start:fragment_end], args.template, output_files[i], extension, verifyResults)

if __name__ == "__main__":
main()
9 changes: 5 additions & 4 deletions tests/math_builtin_api/modules/test_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,13 +425,14 @@ def bad_mutation(type1, type2, mutation):
return True


def expand_signature(types, signature):
def expand_signature(types, signature, silent=False):
"""
Produces all possible overloads of a function signature.
We produce the dict of typelists matched_typelists where each line (with the same index in typelists)
contains possible set of individual types for function arguments and return type.
"""
print("signature: " + str(signature.ret_type) + " " + signature.name + " " + str(signature.arg_types))
if not silent:
print("signature: " + str(signature.ret_type) + " " + signature.name + " " + str(signature.arg_types))

exp_sig = []

Expand Down Expand Up @@ -513,11 +514,11 @@ def get_unique_signatures(signatures):

return uniq_sig

def expand_signatures(types, signatures):
def expand_signatures(types, signatures, silent=False):
ex_sig_list = []

for sig in signatures:
ex_sig_list.extend(expand_signature(types, sig))
ex_sig_list.extend(expand_signature(types, sig, silent))

return get_unique_signatures(ex_sig_list)

Expand Down

0 comments on commit eecbab4

Please sign in to comment.