/* * Copyright 2008-2013 NVIDIA Corporation * Modifications Copyright© 2019-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_real_assertions.hpp" #include "test_utils.hpp" TESTS_DEFINE(UninitializedFillTests, FullTestsParams); template void uninitialized_fill(my_system& system, ForwardIterator, ForwardIterator, const T&) { system.validate_dispatch(); } TEST(UninitializedFillTests, TestUninitializedFillDispatchExplicit) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); thrust::device_vector vec(1); my_system sys(0); thrust::uninitialized_fill(sys, vec.begin(), vec.begin(), 0); ASSERT_EQ(true, sys.is_valid()); } template void uninitialized_fill(my_tag, ForwardIterator first, ForwardIterator, const T&) { *first = 13; } TEST(UninitializedFillTests, TestUninitializedFillDispatchImplicit) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); thrust::device_vector vec(1); thrust::uninitialized_fill(thrust::retag(vec.begin()), thrust::retag(vec.begin()), 0); ASSERT_EQ(13, vec.front()); } template ForwardIterator uninitialized_fill_n(my_system& system, ForwardIterator first, Size, const T&) { system.validate_dispatch(); return first; } TEST(UninitializedFillTests, TestUninitializedFillNDispatchExplicit) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); thrust::device_vector vec(1); my_system sys(0); thrust::uninitialized_fill_n(sys, vec.begin(), vec.size(), 0); ASSERT_EQ(true, sys.is_valid()); } template ForwardIterator uninitialized_fill_n(my_tag, ForwardIterator first, Size, const T&) { *first = 13; return first; } TEST(UninitializedFillTests, TestUninitializedFillNDispatchImplicit) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); thrust::device_vector vec(1); my_system sys(0); thrust::uninitialized_fill_n(sys, vec.begin(), vec.size(), 0); ASSERT_EQ(true, sys.is_valid()); } TYPED_TEST(UninitializedFillTests, TestUninitializedFillPOD) { using Vector = typename TestFixture::input_type; using T = typename Vector::value_type; SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); Vector v{0, 1, 2, 3, 4}; T exemplar(7); thrust::uninitialized_fill(v.begin() + 1, v.begin() + 4, exemplar); Vector ref{0, exemplar, exemplar, exemplar, 4}; ASSERT_EQ(v, ref); exemplar = 8; thrust::uninitialized_fill(v.begin() + 0, v.begin() + 3, exemplar); ref = {exemplar, exemplar, exemplar, 7, 4}; ASSERT_EQ(v, ref); exemplar = 9; thrust::uninitialized_fill(v.begin() + 2, v.end(), exemplar); ref = {8, 8, exemplar, exemplar, 9}; ASSERT_EQ(v, ref); exemplar = 1; thrust::uninitialized_fill(v.begin(), v.end(), exemplar); ref = {exemplar, exemplar, exemplar, exemplar, exemplar}; ASSERT_EQ(v, ref); } struct CopyConstructTest { THRUST_HOST_DEVICE CopyConstructTest() : copy_constructed_on_host(false) , copy_constructed_on_device(false) {} THRUST_HOST_DEVICE CopyConstructTest(const CopyConstructTest&) { NV_IF_TARGET(NV_IS_DEVICE, (copy_constructed_on_device = true; copy_constructed_on_host = false;), (copy_constructed_on_device = false; copy_constructed_on_host = true;)); } THRUST_HOST_DEVICE CopyConstructTest& operator=(const CopyConstructTest& x) { copy_constructed_on_host = x.copy_constructed_on_host; copy_constructed_on_device = x.copy_constructed_on_device; return *this; } bool copy_constructed_on_host; bool copy_constructed_on_device; }; /* TODO: Disabled test * The x = v1[0] call a host copy contructor and we need to * investigate why. TEST(UninitializedFillTests, TestUninitializedFillNonPOD) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); using T = CopyConstructTest; thrust::device_ptr v = thrust::device_malloc(5); T exemplar; ASSERT_EQ(false, exemplar.copy_constructed_on_device); ASSERT_EQ(false, exemplar.copy_constructed_on_host); T host_copy_of_exemplar(exemplar); ASSERT_EQ(false, exemplar.copy_constructed_on_device); ASSERT_EQ(true, exemplar.copy_constructed_on_host); // copy construct v from the exemplar thrust::uninitialized_fill(v, v + 1, exemplar); T x; ASSERT_EQ(false, x.copy_constructed_on_device); ASSERT_EQ(false, x.copy_constructed_on_host); x = v[0]; ASSERT_EQ(true, x.copy_constructed_on_device); ASSERT_EQ(false, x.copy_constructed_on_host); thrust::device_free(v); } */ TYPED_TEST(UninitializedFillTests, TestUninitializedFillNPOD) { using Vector = typename TestFixture::input_type; using T = typename Vector::value_type; SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); Vector v{0, 1, 2, 3, 4}; T exemplar(7); typename Vector::iterator iter = thrust::uninitialized_fill_n(v.begin() + 1, 3, exemplar); Vector ref{0, exemplar, exemplar, exemplar, 4}; ASSERT_EQ_QUIET(v.begin() + 4, iter); exemplar = 8; iter = thrust::uninitialized_fill_n(v.begin() + 0, 3, exemplar); ref = {exemplar, exemplar, exemplar, 7, 4}; ASSERT_EQ_QUIET(v.begin() + 3, iter); exemplar = 9; iter = thrust::uninitialized_fill_n(v.begin() + 2, 3, exemplar); ref = {8, 8, exemplar, exemplar, 9}; ASSERT_EQ_QUIET(v.end(), iter); exemplar = 1; iter = thrust::uninitialized_fill_n(v.begin(), v.size(), exemplar); ref = {exemplar, exemplar, exemplar, exemplar, exemplar}; ASSERT_EQ_QUIET(v.end(), iter); } /* TODO: Disabled test * The x = v1[0] call a host copy contructor and we need to * investigate why. TEST(UninitializedFillTests, TestUninitializedFillNNonPOD) { using T = CopyConstructTest; thrust::device_ptr v = thrust::device_malloc(5); SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); T exemplar; ASSERT_EQ(false, exemplar.copy_constructed_on_device); ASSERT_EQ(false, exemplar.copy_constructed_on_host); T host_copy_of_exemplar(exemplar); ASSERT_EQ(false, exemplar.copy_constructed_on_device); ASSERT_EQ(true, exemplar.copy_constructed_on_host); // copy construct v from the exemplar thrust::uninitialized_fill_n(v, 1, exemplar); T x; ASSERT_EQ(false, x.copy_constructed_on_device); ASSERT_EQ(false, x.copy_constructed_on_host); x = v[0]; ASSERT_EQ(true, x.copy_constructed_on_device); ASSERT_EQ(false, x.copy_constructed_on_host); thrust::device_free(v); } */ __global__ THRUST_HIP_LAUNCH_BOUNDS_DEFAULT void UninitializedFillKernel(int const N, int* array, int fill_value) { if (threadIdx.x == 0) { thrust::device_ptr begin(array); thrust::device_ptr end(array + N); thrust::uninitialized_fill(thrust::hip::par, begin, end, fill_value); } } TEST(UninitializedFillTests, TestUninitializedFillDevice) { SCOPED_TRACE(testing::Message() << "with device_id= " << test::set_device_from_ctest()); 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 h_data = get_random_data(size, 0, size, seed); thrust::device_vector d_data = h_data; int fill_value = get_random_data(1, 0, size, seed)[0]; SCOPED_TRACE(testing::Message() << "with fill_value= " << fill_value); thrust::uninitialized_fill(h_data.begin(), h_data.end(), fill_value); hipLaunchKernelGGL( UninitializedFillKernel, dim3(1, 1, 1), dim3(128, 1, 1), 0, 0, size, thrust::raw_pointer_cast(&d_data[0]), fill_value); HIP_CHECK(hipGetLastError()); ASSERT_EQ(h_data, d_data); } } }