Skip to content
This repository has been archived by the owner on Mar 21, 2024. It is now read-only.

Add async scan algorithms #1251

Merged
merged 2 commits into from
Jan 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmake/ThrustHeaderTesting.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ foreach(thrust_target IN LISTS THRUST_TARGETS)
async/copy.h
async/for_each.h
async/reduce.h
async/scan.h
async/sort.h
async/transform.h
event.h
Expand Down
1 change: 1 addition & 0 deletions testing/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ foreach(thrust_target IN LISTS THRUST_TARGETS)
endforeach()

# Add specialized tests:
add_subdirectory(async)
add_subdirectory(cmake)
add_subdirectory(cpp)
add_subdirectory(cuda)
Expand Down
80 changes: 80 additions & 0 deletions testing/async/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# The async tests perform a large amount of codegen, making them expensive to
# build and test. To keep compilation and runtimes manageable, the tests are
# broken up into many files per algorithm to enable parallelism during
# compilation and testing. The structure of these test directories are:
#
# thrust/testing/async/<algorithm_name>/<unit_test>.cu
#
# These generate executables and CTest tests named
# ${config_prefix}.test.async.<algorithm_name>.<unit_test>.

# The async tests only support CUDA enabled configs. Create a list of valid
# thrust targets:
set(cuda_configs)
foreach(thrust_target IN LISTS THRUST_TARGETS)
thrust_get_target_property(config_device ${thrust_target} DEVICE)
if (config_device STREQUAL CUDA)
list(APPEND cuda_configs ${thrust_target})
endif()
endforeach()

list(LENGTH cuda_configs num_cuda_configs)
if (num_cuda_configs EQUAL 0)
return() # No valid configs found, nothing to do.
endif()

# Process a single algorithm directory, adding all .cu/cpp files as tests for
# each valid backend. algo_name is the name of the subdir (<algorithm_name>
# above) and is used for naming the executable/targets.
function(thrust_add_async_test_dir algo_name)
file(GLOB test_srcs
RELATIVE "${CMAKE_CURRENT_LIST_DIR}"
CONFIGURE_DEPENDS
"${algo_name}/*.cu"
"${algo_name}/*.cpp"
)

# Per-algorithm, all-config metatarget: thrust.all.test.async.[algo].all
set(algo_meta_target thrust.all.test.async.${algo_name}.all)
add_custom_target(${algo_meta_target})

foreach(thrust_target IN LISTS cuda_configs)
thrust_get_target_property(config_prefix ${thrust_target} PREFIX)

# Per-algorithm, per-config metatarget: thrust.[config].test.async.[algo].all
set(algo_config_meta_target ${config_prefix}.test.async.${algo_name}.all)
add_custom_target(${algo_config_meta_target})
add_dependencies(${algo_meta_target} ${algo_config_meta_target})

foreach(test_src IN LISTS test_srcs)
get_filename_component(test_name "${test_src}" NAME_WLE)
string(PREPEND test_name async.${algo_name}.)

thrust_add_test(test_target ${test_name} "${test_src}" ${thrust_target})
if(THRUST_ENABLE_TESTS_WITH_RDC)
thrust_enable_rdc_for_cuda_target(${test_target})
endif()

add_dependencies(${algo_config_meta_target} ${test_target})
endforeach()
endforeach()
endfunction()

# Grab all algorithm subdirectories:
set(test_dirs)
file(GLOB contents
CONFIGURE_DEPENDS
"${CMAKE_CURRENT_LIST_DIR}/*"
)

foreach(test_dir IN LISTS contents)
if(IS_DIRECTORY "${test_dir}")
list(APPEND test_dirs "${test_dir}")
endif()
endforeach()

# Process all test dirs:
foreach(test_dir IN LISTS test_dirs)
get_filename_component(algo_name "${test_dir}" NAME_WLE)
thrust_add_async_test_dir(${algo_name})
endforeach()
46 changes: 46 additions & 0 deletions testing/async/exclusive_scan/counting_iterator.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include <thrust/detail/config.h>

#if THRUST_CPP_DIALECT >= 2014

#include <async/test_policy_overloads.h>

#include <async/exclusive_scan/mixin.h>

#include <algorithm>
#include <limits>

template <typename input_value_type,
typename output_value_type = input_value_type,
typename initial_value_type = input_value_type,
typename alternate_binary_op = thrust::maximum<>>
struct invoker
: testing::async::mixin::input::counting_iterator_from_0<input_value_type>
, testing::async::mixin::output::device_vector<output_value_type>
, testing::async::exclusive_scan::mixin::postfix_args::
all_overloads<initial_value_type, alternate_binary_op>
, testing::async::exclusive_scan::mixin::invoke_reference::
host_synchronous<input_value_type, output_value_type>
, testing::async::exclusive_scan::mixin::invoke_async::simple
, testing::async::mixin::compare_outputs::assert_almost_equal_if_fp_quiet
{
static std::string description()
{
return "fancy input iterator (counting_iterator)";
}
};

template <typename T>
struct test_counting_iterator
{
void operator()(std::size_t num_values) const
{
num_values = unittest::truncate_to_max_representable<T>(num_values);
testing::async::test_policy_overloads<invoker<T>>::run(num_values);
}
};
// Use built-in types only, counting_iterator doesn't seem to be compatible with
// the custom_numeric.
DECLARE_GENERIC_SIZED_UNITTEST_WITH_TYPES(test_counting_iterator,
BuiltinNumericTypes);

#endif // C++14
38 changes: 38 additions & 0 deletions testing/async/exclusive_scan/discard_output.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include <thrust/detail/config.h>

#if THRUST_CPP_DIALECT >= 2014

#include <async/test_policy_overloads.h>

#include <async/exclusive_scan/mixin.h>

// Compilation test with discard iterators. No runtime validation is actually
// performed, other than testing whether the algorithm completes without
// exception.

template <typename input_value_type,
typename initial_value_type = input_value_type,
typename alternate_binary_op = thrust::maximum<>>
struct discard_invoker
: testing::async::mixin::input::device_vector<input_value_type>
, testing::async::mixin::output::discard_iterator
, testing::async::exclusive_scan::mixin::postfix_args::
all_overloads<initial_value_type, alternate_binary_op>
, testing::async::mixin::invoke_reference::noop
, testing::async::exclusive_scan::mixin::invoke_async::simple
, testing::async::mixin::compare_outputs::noop
{
static std::string description() { return "discard output"; }
};

template <typename T>
struct test_discard
{
void operator()(std::size_t num_values) const
{
testing::async::test_policy_overloads<discard_invoker<T>>::run(num_values);
}
};
DECLARE_GENERIC_SIZED_UNITTEST_WITH_TYPES(test_discard, NumericTypes);

#endif // C++14
Loading