// SPDX-FileCopyrightText: Copyright (c) 2011-2022, NVIDIA CORPORATION. All rights reserved. // SPDX-License-Identifier: BSD-3 /****************************************************************************** * Test of BlockHistogram utilities ******************************************************************************/ // Ensure printing of CUDA runtime errors to console #define CUB_STDERR #include #include #include #include template __global__ void block_histogram_kernel(T* d_samples, HistoCounter* d_histogram) { // Parameterize BlockHistogram type for our thread block using block_histogram_t = cub::BlockHistogram; // Allocate temp storage in shared memory __shared__ typename block_histogram_t::TempStorage temp_storage; // Per-thread tile data T data[ITEMS_PER_THREAD]; cub::LoadDirectStriped(threadIdx.x, d_samples, data); // Test histo (writing directly to histogram buffer in global) block_histogram_t(temp_storage).Histogram(data, d_histogram); } template void block_histogram(c2h::device_vector& d_samples, c2h::device_vector& d_histogram) { block_histogram_kernel <<<1, ThreadsInBlock>>>(thrust::raw_pointer_cast(d_samples.data()), thrust::raw_pointer_cast(d_histogram.data())); REQUIRE(cudaSuccess == cudaPeekAtLastError()); REQUIRE(cudaSuccess == cudaDeviceSynchronize()); } // %PARAM% TEST_BINS bins 32:256:1024 using types = c2h::type_list; using threads_in_block = c2h::enum_type_list; using items_per_thread = c2h::enum_type_list; using bins = c2h::enum_type_list; using algorithms = c2h::enum_type_list; template struct params_t { using sample_t = typename c2h::get<0, TestType>; static constexpr int items_per_thread = c2h::get<1, TestType>::value; static constexpr int threads_in_block = c2h::get<2, TestType>::value; static constexpr int bins = c2h::get<3, TestType>::value; static constexpr int num_samples = threads_in_block * items_per_thread; static constexpr cub::BlockHistogramAlgorithm algorithm = c2h::get<4, TestType>::value; }; C2H_TEST("Block histogram can be computed with uniform input", "[histogram][block]", types, items_per_thread, threads_in_block, bins, algorithms) { using params = params_t; using sample_t = typename params::sample_t; const sample_t uniform_value = static_cast(GENERATE_COPY(take(10, random(0, params::bins - 1)))); c2h::host_vector h_samples(params::num_samples, uniform_value); c2h::host_vector h_reference(params::bins); h_reference[static_cast(uniform_value)] = params::num_samples; // Allocate problem device arrays c2h::device_vector d_samples = h_samples; c2h::device_vector d_histogram(params::bins); // Run kernel block_histogram( d_samples, d_histogram); REQUIRE(h_reference == d_histogram); } template c2h::host_vector compute_host_reference(int bins, const c2h::host_vector& h_samples) { c2h::host_vector h_reference(bins); for (const SampleT& sample : h_samples) { h_reference[sample]++; } return h_reference; } C2H_TEST("Block histogram can be computed with modulo input", "[histogram][block]", types, items_per_thread, threads_in_block, bins, algorithms) { using params = params_t; using sample_t = typename params::sample_t; // Allocate problem device arrays c2h::device_vector d_histogram(params::bins); c2h::device_vector d_samples(params::num_samples); c2h::gen(c2h::modulo_t{params::bins}, d_samples); c2h::host_vector h_samples = d_samples; auto h_reference = compute_host_reference(params::bins, h_samples); // Run kernel block_histogram( d_samples, d_histogram); REQUIRE(h_reference == d_histogram); } C2H_TEST("Block histogram can be computed with random input", "[histogram][block]", types, items_per_thread, threads_in_block, bins, algorithms) { using params = params_t; using sample_t = typename params::sample_t; // Allocate problem device arrays c2h::device_vector d_histogram(params::bins); c2h::device_vector d_samples(params::num_samples); const sample_t min_bin = static_cast(0); const sample_t max_bin = static_cast( std::min(static_cast(cuda::std::numeric_limits::max()), static_cast(params::bins - 1))); c2h::gen(C2H_SEED(10), d_samples, min_bin, max_bin); c2h::host_vector h_samples = d_samples; auto h_reference = compute_host_reference(params::bins, h_samples); // Run kernel block_histogram( d_samples, d_histogram); REQUIRE(h_reference == d_histogram); }