/* * Copyright© 2024-2025 Advanced Micro Devices, Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include "test_param_fixtures.hpp" #include "test_utils.hpp" TESTS_DEFINE(AsyncScanTests, NumericalTestsParams) THRUST_SUPPRESS_DEPRECATED_PUSH enum wait_policy { wait_for_futures, do_not_wait_for_futures }; #define FIRST_ARG(N, ...) N #define SECOND_ARG(N, ...) FIRST_ARG(__VA_ARGS__) #define DEFINE_INCLUSIVE_SCAN_INVOKER(name, ...) \ template \ struct name \ { \ template \ __host__ static void sync(ForwardIt&& first, Sentinel&& last, OutputIt&& out) \ { \ ::thrust::inclusive_scan( \ THRUST_FWD(first), \ THRUST_FWD(last), \ THRUST_FWD(out) THRUST_PP_COMMA_IF(THRUST_PP_ARITY(FIRST_ARG(__VA_ARGS__))) FIRST_ARG(__VA_ARGS__)); \ } \ \ template \ __host__ static auto async(ForwardIt&& first, Sentinel&& last, OutputIt&& out) \ THRUST_DECLTYPE_RETURNS(::thrust::async::inclusive_scan( \ SECOND_ARG(__VA_ARGS__) THRUST_PP_COMMA_IF(THRUST_PP_ARITY(SECOND_ARG(__VA_ARGS__))) THRUST_FWD(first), \ THRUST_FWD(last), \ THRUST_FWD(out) THRUST_PP_COMMA_IF(THRUST_PP_ARITY(FIRST_ARG(__VA_ARGS__))) FIRST_ARG(__VA_ARGS__))) \ } /**/ #define DEFINE_EXCLUSIVE_SCAN_INVOKER(name, init, ...) \ template \ struct name \ { \ template \ __host__ static void sync(ForwardIt&& first, Sentinel&& last, OutputIt&& out) \ { \ ::thrust::exclusive_scan( \ THRUST_FWD(first), \ THRUST_FWD(last), \ THRUST_FWD(out), \ init THRUST_PP_COMMA_IF(THRUST_PP_ARITY(FIRST_ARG(__VA_ARGS__))) FIRST_ARG(__VA_ARGS__)); \ } \ \ template \ __host__ static auto async(ForwardIt&& first, Sentinel&& last, OutputIt&& out) \ THRUST_DECLTYPE_RETURNS(::thrust::async::exclusive_scan( \ SECOND_ARG(__VA_ARGS__) THRUST_PP_COMMA_IF(THRUST_PP_ARITY(SECOND_ARG(__VA_ARGS__))) THRUST_FWD(first), \ THRUST_FWD(last), \ THRUST_FWD(out), \ init THRUST_PP_COMMA_IF(THRUST_PP_ARITY(FIRST_ARG(__VA_ARGS__))) FIRST_ARG(__VA_ARGS__))) \ } /**/ DEFINE_INCLUSIVE_SCAN_INVOKER(inclusive_scan_invoker); DEFINE_INCLUSIVE_SCAN_INVOKER(inclusive_scan_invoker_device, thrust::plus{}, thrust::device); DEFINE_EXCLUSIVE_SCAN_INVOKER(exclusive_scan_invoker, T(0)); DEFINE_EXCLUSIVE_SCAN_INVOKER(exclusive_scan_invoker_device, T(0), thrust::plus{}, thrust::device); DEFINE_INCLUSIVE_SCAN_INVOKER(inclusive_scan_invoker_maximum, thrust::maximum{}); DEFINE_INCLUSIVE_SCAN_INVOKER(inclusive_scan_invoker_maximum_device, thrust::maximum{}, thrust::device); DEFINE_EXCLUSIVE_SCAN_INVOKER(exclusive_scan_invoker_maximum, T(1), thrust::maximum{}); DEFINE_EXCLUSIVE_SCAN_INVOKER(exclusive_scan_invoker_maximum_device, T(1), thrust::maximum{}, thrust::device); #undef DEFINE_SCAN_INVOKER #undef DEFINE_SCAN_OP_INVOKER #undef FIRST_ARG #undef SECOND_ARD /////////////////////////////////////////////////////////////////////////////// template class ScanInvoker, wait_policy WaitPolicy> void TestAsyncScan() { for (auto size : get_sizes()) { SCOPED_TRACE(testing::Message() << "with size = " << size); for (auto seed : get_seeds()) { SCOPED_TRACE(testing::Message() << "with seed= " << seed); thrust::host_vector h0_data = get_random_data(size, get_default_limits::min(), get_default_limits::max(), seed); thrust::device_vector d0_data(h0_data); thrust::host_vector h0_output(h0_data); thrust::device_vector d0_output(d0_data); ScanInvoker::sync(h0_data.begin(), h0_data.end(), h0_output.begin()); auto f0 = ScanInvoker::async(d0_data.begin(), d0_data.end(), d0_output.begin()); THRUST_IF_CONSTEXPR (wait_for_futures == WaitPolicy) { f0.wait(); test_equality_scan(h0_output, d0_output); } } } } TYPED_TEST(AsyncScanTests, AsyncInclusiveScan) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); using T = typename TestFixture::input_type; TestAsyncScan(); }; TYPED_TEST(AsyncScanTests, AsyncInclusiveScanNoWait) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); using T = typename TestFixture::input_type; TestAsyncScan(); }; TYPED_TEST(AsyncScanTests, AsyncInclusiveScanPolicy) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); using T = typename TestFixture::input_type; TestAsyncScan(); }; TYPED_TEST(AsyncScanTests, AsyncInclusiveScanMaximum) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); using T = typename TestFixture::input_type; TestAsyncScan(); }; TYPED_TEST(AsyncScanTests, AsyncInclusiveScanMaximumNoWait) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); using T = typename TestFixture::input_type; TestAsyncScan(); }; TYPED_TEST(AsyncScanTests, AsyncInclusiveScanPolicyMaximum) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); using T = typename TestFixture::input_type; TestAsyncScan(); }; TYPED_TEST(AsyncScanTests, AsyncInclusiveScanPolicyMaximumNoWait) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); using T = typename TestFixture::input_type; TestAsyncScan(); }; TYPED_TEST(AsyncScanTests, AsyncExclusiveScan) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); using T = typename TestFixture::input_type; TestAsyncScan(); }; TYPED_TEST(AsyncScanTests, AsyncExclusiveScanNoWait) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); using T = typename TestFixture::input_type; TestAsyncScan(); }; TYPED_TEST(AsyncScanTests, AsyncExclusiveScanPolicy) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); using T = typename TestFixture::input_type; TestAsyncScan(); }; TYPED_TEST(AsyncScanTests, AsyncExclusiveScanMaximum) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); using T = typename TestFixture::input_type; TestAsyncScan(); }; TYPED_TEST(AsyncScanTests, AsyncExclusiveScanMaximumNoWait) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); using T = typename TestFixture::input_type; TestAsyncScan(); }; TYPED_TEST(AsyncScanTests, AsyncExclusiveScanPolicyMaximum) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); using T = typename TestFixture::input_type; TestAsyncScan(); }; TYPED_TEST(AsyncScanTests, AsyncExclusiveScanPolicyMaximumNoWait) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); using T = typename TestFixture::input_type; TestAsyncScan(); }; ///////////////////////////////////////////////////////////////////////////////