Thrust#

One address space means a device_vector IS a host vector; the algorithms are the <algorithm>/<numeric> ones. Execution-policy tags (thrust::host/device) are accepted and ignored.

Defined in code/simulator.h.

This page documents 47 symbols: 47 functions.

Functions#

Signature

Description

Availability

Location

Example

inline Out copy(In f, In l, Out o)

sim only

simulator.h:2706

View

inline Out copy(simExecPolicy, In f, In l, Out o)

sim only

simulator.h:2742

View

inline std::ptrdiff_t count(It f, It l, const T& v)

sim only

simulator.h:2734

View

inline std::ptrdiff_t count_if(It f, It l, P p)

sim only

simulator.h:2735

View

inline device_ptr<T> device_pointer_cast(T* p)

sim only

simulator.h:2695

explicit device_ptr(T* q) : p(q)

sim only

simulator.h:2683

inline Out exclusive_scan(In f, In l, Out o)

sim only

simulator.h:2724

inline Out exclusive_scan(simExecPolicy, In f, In l, Out o)

sim only

simulator.h:2745

inline void fill(It f, It l, const T& v)

sim only

simulator.h:2707

View

std::vector<std::ptrdiff_t> idx(static_cast<size_t>(n))

sim only

simulator.h:2749

View

inline Out inclusive_scan(In f, In l, Out o)

sim only

simulator.h:2723

View

inline Out inclusive_scan(simExecPolicy, In f, In l, Out o)

sim only

simulator.h:2744

View

inline bool is_sorted(It f, It l)

sim only

simulator.h:2717

View

inline bool is_sorted(It f, It l, C c)

sim only

simulator.h:2718

View

std::vector<typename std::iterator_traits<KIt>::value_type> k2(static_cast<size_t>(n))

sim only

simulator.h:2753

inline It max_element(It f, It l)

sim only

simulator.h:2737

inline It min_element(It f, It l)

sim only

simulator.h:2736

bool operator!=(const device_ptr& o) const

sim only

simulator.h:2693

T& operator*() const

sim only

simulator.h:2684

device_ptr operator+(std::ptrdiff_t i) const

sim only

simulator.h:2688

device_ptr& operator++()

sim only

simulator.h:2691

device_ptr operator-(std::ptrdiff_t i) const

sim only

simulator.h:2689

std::ptrdiff_t operator-(const device_ptr& o) const

sim only

simulator.h:2690

T* operator->() const

sim only

simulator.h:2685

bool operator==(const device_ptr& o) const

sim only

simulator.h:2692

T& operator[](std::ptrdiff_t i) const

sim only

simulator.h:2686

inline T* raw_pointer_cast(const device_ptr<T>& p)

sim only

simulator.h:2696

inline T* raw_pointer_cast(T* p)

sim only

simulator.h:2697

inline T* raw_pointer_cast(std::vector<T>& v)

sim only

simulator.h:2698

inline T reduce(It f, It l, T init)

sim only

simulator.h:2719

View

inline typename std::iterator_traits<It>::value_type reduce(It f, It l)

sim only

simulator.h:2720

View

inline T reduce(simExecPolicy, It f, It l, T init)

sim only

simulator.h:2743

View

inline It remove(It f, It l, const T& v)

sim only

simulator.h:2700

View

inline It remove(simExecPolicy, It f, It l, const T& v)

Execution-policy overloads: the tag is accepted and dropped.

sim only

simulator.h:2739

View

inline It remove_if(It f, It l, P p)

sim only

simulator.h:2701

inline It remove_if(simExecPolicy, It f, It l, P p)

sim only

simulator.h:2740

inline void sequence(It f, It l, T init)

sim only

simulator.h:2708

View

inline void sequence(It f, It l)

2-argument form: the value type is deduced from the iterator (a defaulted template parameter cannot be, which is why both spellings are needed).

sim only

simulator.h:2713

View

inline void sort(It f, It l)

sim only

simulator.h:2702

View

inline void sort(It f, It l, C c)

sim only

simulator.h:2703

View

inline void sort(simExecPolicy, It f, It l)

sim only

simulator.h:2741

View

inline void sort_by_key(KIt kf, KIt kl, VIt vf)

sort_by_key: co-sort a values range by its keys.

sim only

simulator.h:2747

View

inline void stable_sort(It f, It l)

sim only

simulator.h:2704

inline void stable_sort(It f, It l, C c)

sim only

simulator.h:2705

inline Out transform(In f, In l, Out o, Op op)

sim only

simulator.h:2729

inline Out transform(In1 f, In1 l, In2 g, Out o, Op op)

sim only

simulator.h:2732

std::vector<typename std::iterator_traits<VIt>::value_type> v2(static_cast<size_t>(n))

sim only

simulator.h:2754

Examples#

Code from the repository’s example corpus (code\*.cu); the highlighted line is the call site. These blocks are what the View links above open.

copy (test_web_cs_radixsort_thrust.cu:119)
109        float time = 0;
110        check(cudaEventElapsedTime(&time, start_event, stop_event), "cudaEventElapsedTime");
111        totalTime += time;
112    }
113    totalTime /= (1.0e3f * numIterations);
114    std::printf("radixSortThrust, Throughput = %.4f MElements/s, Time = %.5f s, Size = %u elements\n",
115                1.0e-6f * numElements / totalTime, totalTime, numElements);
116    check(cudaGetLastError(), "after radixsort");
117
118    // Get results back to host for correctness checking
119    thrust::copy(d_keys.begin(), d_keys.end(), h_keysSorted.begin());
120    if (!keysOnly) thrust::copy(d_values.begin(), d_values.end(), h_values.begin());
121    check(cudaGetLastError(), "copying results to host memory");
122
123    check(cudaEventDestroy(start_event), "cudaEventDestroy(start)");
124    check(cudaEventDestroy(stop_event), "cudaEventDestroy(stop)");
125
126    // Check 1 (the sample's): the keys come back in order.
127    bool bTestResult = std::is_sorted(h_keysSorted.begin(), h_keysSorted.end());
128    if (!bTestResult) std::printf("  output is not sorted\n");
129
130    // Check 2 [SIM]: sorted keys are a permutation of the input.
copy (test_web_cs_radixsort_thrust.cu:119)
109        float time = 0;
110        check(cudaEventElapsedTime(&time, start_event, stop_event), "cudaEventElapsedTime");
111        totalTime += time;
112    }
113    totalTime /= (1.0e3f * numIterations);
114    std::printf("radixSortThrust, Throughput = %.4f MElements/s, Time = %.5f s, Size = %u elements\n",
115                1.0e-6f * numElements / totalTime, totalTime, numElements);
116    check(cudaGetLastError(), "after radixsort");
117
118    // Get results back to host for correctness checking
119    thrust::copy(d_keys.begin(), d_keys.end(), h_keysSorted.begin());
120    if (!keysOnly) thrust::copy(d_values.begin(), d_values.end(), h_values.begin());
121    check(cudaGetLastError(), "copying results to host memory");
122
123    check(cudaEventDestroy(start_event), "cudaEventDestroy(start)");
124    check(cudaEventDestroy(stop_event), "cudaEventDestroy(stop)");
125
126    // Check 1 (the sample's): the keys come back in order.
127    bool bTestResult = std::is_sorted(h_keysSorted.begin(), h_keysSorted.end());
128    if (!bTestResult) std::printf("  output is not sorted\n");
129
130    // Check 2 [SIM]: sorted keys are a permutation of the input.
count (test_web_ndb_cpp11.cu:111)
101  cudaMemcpy(d_text, corpus, len, cudaMemcpyHostToDevice);
102
103  int count = 0;
104  int *d_count;
105  cudaMalloc(&d_count, sizeof(int));
106  cudaMemset(d_count, 0, sizeof(int));
107
108  LAUNCH(xyzw_frequency, 8, 256, d_count, d_text, len);   // [SIM]
109  cudaMemcpy(&count, d_count, sizeof(int), cudaMemcpyDeviceToHost);
110
111  std::cout << "counted " << count << " instances of 'x', 'y', 'z', or 'w' "
112            << "(expected " << expected << ")" << std::endl;
113  const bool ok = (count == expected);
114  std::printf("C++11 grid-stride count_if: %s\n", ok ? "PASSED" : "FAILED");
115
116  cudaFree(d_count);
117  cudaFree(d_text);
118  return ok ? 0 : 1;
119}
count_if (test_web_ndb_cpp11.cu:52)
42    __host__ __device__ bool operator!=(const iter& o) const { return cur < o.cur; }
43  };
44  __host__ __device__ iter begin() const { return { begin_, step_ }; }
45  __host__ __device__ iter end()   const { return { end_,   step_ }; }
46};
47/////////////////////////////////////////////////////////////////
48
49// verbatim device function template from the source repo
50template <typename T, typename Predicate>
51__device__
52void count_if(int *count, T *data, int n, Predicate p)
53{
54  for (auto i : grid_stride_range(0, n)) {
55    if (p(data[i])) atomicAdd(count, 1);
56  }
57}
58
59// verbatim kernel: lambda that searches for x, y, z or w (range-based for +
60// initializer_list inside the functor; auto so the array/functor types are implicit)
61__global__
62void xyzw_frequency(int *count, char *text, int n)
63{
fill (test_web_cs_transpose.cu:289)
279        case 1: kernel = &copySharedMem;            kernelName = "shared memory copy"; break;
280        case 2: kernel = &transposeNaive;           kernelName = "naive             "; break;
281        case 3: kernel = &transposeCoalesced;       kernelName = "coalesced         "; break;
282        case 4: kernel = &transposeNoBankConflicts; kernelName = "optimized         "; break;
283        case 5: kernel = &transposeCoarseGrained;   kernelName = "coarse-grained    "; break;
284        case 6: kernel = &transposeFineGrained;     kernelName = "fine-grained      "; break;
285        case 7: kernel = &transposeDiagonal;        kernelName = "diagonal          "; break;
286        }
287
288        // reset output between kernels (as the sample does)
289        std::fill(h_odata.begin(), h_odata.end(), 0.0f);
290        cudaMemcpy(d_odata, h_odata.data(), mem, cudaMemcpyHostToDevice);
291
292        LAUNCH(kernel, grid, threads, d_odata, d_idata, size_x, size_y);   // [SIM]
293
294        cudaMemcpy(h_odata.data(), d_odata, mem, cudaMemcpyDeviceToHost);
295
296        // pick the reference: copies -> identity; coarse/fine -> partial (skip);
297        // everything else -> full transpose.
298        const bool isCopy    = (kernel == &copy || kernel == &copySharedMem);
299        const bool isPartial = (kernel == &transposeCoarseGrained || kernel == &transposeFineGrained);
300        const float *gold    = isCopy ? h_idata.data() : gold_T.data();
idx (test_llama.cu:190)
180        float e = expf(dot * scale - m);
181        denom += e;
182        num   += e * V[(static_cast<size_t>(j) * N_KV + kvhead) * HEAD_DIM + d];
183    }
184    out[idx] = num / denom;
185}
186
187// Element-wise residual add: out = a + b. One thread per element.
188__global__ void addKernel(const float* a, const float* b, float* out, int n) {
189    int idx = blockIdx.x * blockDim.x + threadIdx.x;
190    if (idx < n) out[idx] = a[idx] + b[idx];
191}
192
193// SwiGLU gate: out = SiLU(gate) ⊙ up, with SiLU(x) = x * sigmoid(x). One
194// thread per element of the (T, 1408) hidden tensor.
195__global__ void swigluKernel(const float* gate, const float* up, float* out, int n) {
196    int idx = blockIdx.x * blockDim.x + threadIdx.x;
197    if (idx < n) {
198        float g = gate[idx];
199        float silu = g / (1.0f + expf(-g));
200        out[idx] = silu * up[idx];
201    }
inclusive_scan (test_web_bf_thrust_scan.cu:72)
62            g_ok = false;
63        }
64}
65
66// --- thrust_scan_vector.cu: scan a thrust::device_vector in place ------------
67static void scan_vector() {
68    thrust::device_vector<int> x(N, 0);
69    thrust::device_vector<int> y(N, 0);
70    for (int i = 0; i < N; ++i) x[i] = i + 1;
71
72    thrust::inclusive_scan(x.begin(), x.end(), y.begin());
73
74    std::vector<int> got(N);
75    std::printf("device_vector: ");
76    for (int i = 0; i < N; ++i) { got[i] = int(y[i]); std::printf("%d ", got[i]); }
77    std::printf("\n");
78    verify(got, "device_vector");
79}
80
81// --- thrust_scan_pointer.cu: scan raw device pointers, thrust::device policy -
82static void scan_pointer() {
83    int *x = nullptr, *y = nullptr;
inclusive_scan (test_web_bf_thrust_scan.cu:72)
62            g_ok = false;
63        }
64}
65
66// --- thrust_scan_vector.cu: scan a thrust::device_vector in place ------------
67static void scan_vector() {
68    thrust::device_vector<int> x(N, 0);
69    thrust::device_vector<int> y(N, 0);
70    for (int i = 0; i < N; ++i) x[i] = i + 1;
71
72    thrust::inclusive_scan(x.begin(), x.end(), y.begin());
73
74    std::vector<int> got(N);
75    std::printf("device_vector: ");
76    for (int i = 0; i < N; ++i) { got[i] = int(y[i]); std::printf("%d ", got[i]); }
77    std::printf("\n");
78    verify(got, "device_vector");
79}
80
81// --- thrust_scan_pointer.cu: scan raw device pointers, thrust::device policy -
82static void scan_pointer() {
83    int *x = nullptr, *y = nullptr;
is_sorted (test_web_cs_radixsort_thrust.cu:127)
117    // Get results back to host for correctness checking
118    thrust::copy(d_keys.begin(), d_keys.end(), h_keysSorted.begin());
119    if (!keysOnly) thrust::copy(d_values.begin(), d_values.end(), h_values.begin());
120    check(cudaGetLastError(), "copying results to host memory");
121
122    check(cudaEventDestroy(start_event), "cudaEventDestroy(start)");
123    check(cudaEventDestroy(stop_event), "cudaEventDestroy(stop)");
124
125    // Check 1 (the sample's): the keys come back in order.
126    bool bTestResult = std::is_sorted(h_keysSorted.begin(), h_keysSorted.end());
127    if (!bTestResult) std::printf("  output is not sorted\n");
128
129    // Check 2 [SIM]: sorted keys are a permutation of the input.
130    {
131        std::vector<T> a(keysOriginal), b(h_keysSorted.begin(), h_keysSorted.end());
132        std::sort(a.begin(), a.end());
133        if (a != b) { std::printf("  output is not a permutation of the input\n"); bTestResult = false; }
134    }
135
136    // Check 3 [SIM]: each payload still points at its own key.
137    if (!keysOnly) {
is_sorted (test_web_cs_radixsort_thrust.cu:127)
117    // Get results back to host for correctness checking
118    thrust::copy(d_keys.begin(), d_keys.end(), h_keysSorted.begin());
119    if (!keysOnly) thrust::copy(d_values.begin(), d_values.end(), h_values.begin());
120    check(cudaGetLastError(), "copying results to host memory");
121
122    check(cudaEventDestroy(start_event), "cudaEventDestroy(start)");
123    check(cudaEventDestroy(stop_event), "cudaEventDestroy(stop)");
124
125    // Check 1 (the sample's): the keys come back in order.
126    bool bTestResult = std::is_sorted(h_keysSorted.begin(), h_keysSorted.end());
127    if (!bTestResult) std::printf("  output is not sorted\n");
128
129    // Check 2 [SIM]: sorted keys are a permutation of the input.
130    {
131        std::vector<T> a(keysOriginal), b(h_keysSorted.begin(), h_keysSorted.end());
132        std::sort(a.begin(), a.end());
133        if (a != b) { std::printf("  output is not a permutation of the input\n"); bTestResult = false; }
134    }
135
136    // Check 3 [SIM]: each payload still points at its own key.
137    if (!keysOnly) {
reduce (test_coop_groups.cu:73)
63    auto tile  = cg::tiled_partition<32>(block);
64    int v = in[gid];
65    for (unsigned d = tile.size() / 2; d > 0; d >>= 1) v += tile.shfl_down(v, d);
66    if (tile.thread_rank() == 0) outWarp[gid / 32u] = v;
67}
68
69// cg::reduce broadcasts the warp sum to every lane.
70__global__ void kCgReduce(const int* in, int* out) {
71    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
72    auto tile = cg::tiled_partition<32>(cg::this_thread_block());
73    out[gid] = cg::reduce(tile, in[gid], cg::plus<int>());
74}
75
76// tile.thread_rank() and meta_group_rank() identify a lane and its warp.
77__global__ void kTileInfo(int* rank, int* warp) {
78    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
79    auto tile = cg::tiled_partition<32>(cg::this_thread_block());
80    rank[gid] = static_cast<int>(tile.thread_rank());
81    warp[gid] = static_cast<int>(tile.meta_group_rank());
82}
83
84static int* upload(const std::vector<int>& h) {
reduce (test_coop_groups.cu:73)
63    auto tile  = cg::tiled_partition<32>(block);
64    int v = in[gid];
65    for (unsigned d = tile.size() / 2; d > 0; d >>= 1) v += tile.shfl_down(v, d);
66    if (tile.thread_rank() == 0) outWarp[gid / 32u] = v;
67}
68
69// cg::reduce broadcasts the warp sum to every lane.
70__global__ void kCgReduce(const int* in, int* out) {
71    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
72    auto tile = cg::tiled_partition<32>(cg::this_thread_block());
73    out[gid] = cg::reduce(tile, in[gid], cg::plus<int>());
74}
75
76// tile.thread_rank() and meta_group_rank() identify a lane and its warp.
77__global__ void kTileInfo(int* rank, int* warp) {
78    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
79    auto tile = cg::tiled_partition<32>(cg::this_thread_block());
80    rank[gid] = static_cast<int>(tile.thread_rank());
81    warp[gid] = static_cast<int>(tile.meta_group_rank());
82}
83
84static int* upload(const std::vector<int>& h) {
reduce (test_coop_groups.cu:73)
63    auto tile  = cg::tiled_partition<32>(block);
64    int v = in[gid];
65    for (unsigned d = tile.size() / 2; d > 0; d >>= 1) v += tile.shfl_down(v, d);
66    if (tile.thread_rank() == 0) outWarp[gid / 32u] = v;
67}
68
69// cg::reduce broadcasts the warp sum to every lane.
70__global__ void kCgReduce(const int* in, int* out) {
71    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
72    auto tile = cg::tiled_partition<32>(cg::this_thread_block());
73    out[gid] = cg::reduce(tile, in[gid], cg::plus<int>());
74}
75
76// tile.thread_rank() and meta_group_rank() identify a lane and its warp.
77__global__ void kTileInfo(int* rank, int* warp) {
78    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
79    auto tile = cg::tiled_partition<32>(cg::this_thread_block());
80    rank[gid] = static_cast<int>(tile.thread_rank());
81    warp[gid] = static_cast<int>(tile.meta_group_rank());
82}
83
84static int* upload(const std::vector<int>& h) {
remove (test_web_olcf_hw9_task2.cu:168)
158    LAUNCH_COOP(my_remove_if<mytype>, grid, block, c_idata, remove_val, d_odata, d_idxs, ds);
159    cudaDeviceSynchronize();
160    cudaMemcpy(h_data.data(), d_odata, tsize, cudaMemcpyDeviceToHost);
161    for (int i = 0; i < val; i++)
162        if (h_data[i] != i) {
163            std::printf("mismatch 2 at %d, was: %d, should be: %d\n", i, h_data[i], i);
164            ok = false; break;
165        }
166
167    // Cross-check against thrust::remove.
168    thrust::remove(t_data.begin(), t_data.end(), -1);
169    thrust::host_vector<mytype> th_data = t_data;
170    for (int i = 0; i < val; i++)
171        if (h_data[i] != th_data[i]) {
172            std::printf("mismatch 3 at %d, was: %d, should be: %d\n", i, th_data[i], h_data[i]);
173            ok = false; break;
174        }
175
176    cudaFree(d_idata);
177    cudaFree(d_odata);
178    cudaFree(d_idxs);
remove (test_web_olcf_hw9_task2.cu:168)
158    LAUNCH_COOP(my_remove_if<mytype>, grid, block, c_idata, remove_val, d_odata, d_idxs, ds);
159    cudaDeviceSynchronize();
160    cudaMemcpy(h_data.data(), d_odata, tsize, cudaMemcpyDeviceToHost);
161    for (int i = 0; i < val; i++)
162        if (h_data[i] != i) {
163            std::printf("mismatch 2 at %d, was: %d, should be: %d\n", i, h_data[i], i);
164            ok = false; break;
165        }
166
167    // Cross-check against thrust::remove.
168    thrust::remove(t_data.begin(), t_data.end(), -1);
169    thrust::host_vector<mytype> th_data = t_data;
170    for (int i = 0; i < val; i++)
171        if (h_data[i] != th_data[i]) {
172            std::printf("mismatch 3 at %d, was: %d, should be: %d\n", i, th_data[i], h_data[i]);
173            ok = false; break;
174        }
175
176    cudaFree(d_idata);
177    cudaFree(d_odata);
178    cudaFree(d_idxs);
sequence (test_web_cs_radixsort_thrust.cu:84)
74    std::mt19937 rng(20220607u);
75    if (floatKeys) {
76        std::uniform_real_distribution<float> u01(0.0f, 1.0f);
77        for (unsigned int i = 0; i < numElements; i++) h_keys[i] = T(u01(rng));
78    } else {
79        std::uniform_int_distribution<unsigned int> u(0, UINT_MAX);
80        for (unsigned int i = 0; i < numElements; i++) h_keys[i] = T(u(rng));
81    }
82    // [SIM] the sample writes thrust::sequence(first, last); the sim only has the
83    // three-argument form, so the start value 0u is spelled out (legal in both).
84    if (!keysOnly) thrust::sequence(h_values.begin(), h_values.end(), 0u);
85
86    // Keep a copy of the unsorted keys so the permutation can be checked.
87    const std::vector<T> keysOriginal(h_keys.begin(), h_keys.end());
88
89    thrust::device_vector<T>            d_keys;
90    thrust::device_vector<unsigned int> d_values;
91
92    cudaEvent_t start_event, stop_event;
93    check(cudaEventCreate(&start_event), "cudaEventCreate(start)");
94    check(cudaEventCreate(&stop_event), "cudaEventCreate(stop)");
sequence (test_web_cs_radixsort_thrust.cu:84)
74    std::mt19937 rng(20220607u);
75    if (floatKeys) {
76        std::uniform_real_distribution<float> u01(0.0f, 1.0f);
77        for (unsigned int i = 0; i < numElements; i++) h_keys[i] = T(u01(rng));
78    } else {
79        std::uniform_int_distribution<unsigned int> u(0, UINT_MAX);
80        for (unsigned int i = 0; i < numElements; i++) h_keys[i] = T(u(rng));
81    }
82    // [SIM] the sample writes thrust::sequence(first, last); the sim only has the
83    // three-argument form, so the start value 0u is spelled out (legal in both).
84    if (!keysOnly) thrust::sequence(h_values.begin(), h_values.end(), 0u);
85
86    // Keep a copy of the unsorted keys so the permutation can be checked.
87    const std::vector<T> keysOriginal(h_keys.begin(), h_keys.end());
88
89    thrust::device_vector<T>            d_keys;
90    thrust::device_vector<unsigned int> d_values;
91
92    cudaEvent_t start_event, stop_event;
93    check(cudaEventCreate(&start_event), "cudaEventCreate(start)");
94    check(cudaEventCreate(&stop_event), "cudaEventCreate(stop)");
sort (test_web_cs_bitonic.cu:140)
130    cudaMemcpy(d_SrcVal, h_val.data(), bytes, cudaMemcpyHostToDevice);
131
132    // Single block, SHARED_SIZE_LIMIT/2 threads (one thread per comparator)
133    LAUNCH(bitonicSortShared, 1, SHARED_SIZE_LIMIT / 2,
134           d_DstKey, d_DstVal, d_SrcKey, d_SrcVal, arrayLength, dir);   // [SIM]
135
136    cudaMemcpy(h_res.data(), d_DstKey, bytes, cudaMemcpyDeviceToHost);
137
138    // CPU reference: std::sort of the same keys
139    std::vector<uint> ref(h_key);
140    std::sort(ref.begin(), ref.end());
141
142    bool ok = true;
143    for (uint i = 0; i < arrayLength; i++)
144        if (h_res[i] != ref[i]) { ok = false; break; }
145
146    std::printf("bitonic sort of %u keys (dir=%u) vs std::sort: %s\n",
147                arrayLength, dir, ok ? "PASSED" : "FAILED");
148
149    cudaFree(d_SrcKey); cudaFree(d_SrcVal); cudaFree(d_DstKey); cudaFree(d_DstVal);
150    return ok ? 0 : 1;
151}
sort (test_web_cs_bitonic.cu:140)
130    cudaMemcpy(d_SrcVal, h_val.data(), bytes, cudaMemcpyHostToDevice);
131
132    // Single block, SHARED_SIZE_LIMIT/2 threads (one thread per comparator)
133    LAUNCH(bitonicSortShared, 1, SHARED_SIZE_LIMIT / 2,
134           d_DstKey, d_DstVal, d_SrcKey, d_SrcVal, arrayLength, dir);   // [SIM]
135
136    cudaMemcpy(h_res.data(), d_DstKey, bytes, cudaMemcpyDeviceToHost);
137
138    // CPU reference: std::sort of the same keys
139    std::vector<uint> ref(h_key);
140    std::sort(ref.begin(), ref.end());
141
142    bool ok = true;
143    for (uint i = 0; i < arrayLength; i++)
144        if (h_res[i] != ref[i]) { ok = false; break; }
145
146    std::printf("bitonic sort of %u keys (dir=%u) vs std::sort: %s\n",
147                arrayLength, dir, ok ? "PASSED" : "FAILED");
148
149    cudaFree(d_SrcKey); cudaFree(d_SrcVal); cudaFree(d_DstKey); cudaFree(d_DstVal);
150    return ok ? 0 : 1;
151}
sort (test_web_cs_bitonic.cu:140)
130    cudaMemcpy(d_SrcVal, h_val.data(), bytes, cudaMemcpyHostToDevice);
131
132    // Single block, SHARED_SIZE_LIMIT/2 threads (one thread per comparator)
133    LAUNCH(bitonicSortShared, 1, SHARED_SIZE_LIMIT / 2,
134           d_DstKey, d_DstVal, d_SrcKey, d_SrcVal, arrayLength, dir);   // [SIM]
135
136    cudaMemcpy(h_res.data(), d_DstKey, bytes, cudaMemcpyDeviceToHost);
137
138    // CPU reference: std::sort of the same keys
139    std::vector<uint> ref(h_key);
140    std::sort(ref.begin(), ref.end());
141
142    bool ok = true;
143    for (uint i = 0; i < arrayLength; i++)
144        if (h_res[i] != ref[i]) { ok = false; break; }
145
146    std::printf("bitonic sort of %u keys (dir=%u) vs std::sort: %s\n",
147                arrayLength, dir, ok ? "PASSED" : "FAILED");
148
149    cudaFree(d_SrcKey); cudaFree(d_SrcVal); cudaFree(d_DstKey); cudaFree(d_DstVal);
150    return ok ? 0 : 1;
151}
sort_by_key (test_web_cs_radixsort_thrust.cu:104)
 94    check(cudaEventCreate(&stop_event), "cudaEventCreate(stop)");
 95
 96    float totalTime = 0;
 97    for (unsigned int i = 0; i < numIterations; i++) {
 98        d_keys = h_keys;                           // reset data before sort
 99        if (!keysOnly) d_values = h_values;
100
101        check(cudaEventRecord(start_event, 0), "cudaEventRecord(start)");
102
103        if (keysOnly) thrust::sort(d_keys.begin(), d_keys.end());
104        else          thrust::sort_by_key(d_keys.begin(), d_keys.end(), d_values.begin());
105
106        check(cudaEventRecord(stop_event, 0), "cudaEventRecord(stop)");
107        check(cudaEventSynchronize(stop_event), "cudaEventSynchronize");
108
109        float time = 0;
110        check(cudaEventElapsedTime(&time, start_event, stop_event), "cudaEventElapsedTime");
111        totalTime += time;
112    }
113    totalTime /= (1.0e3f * numIterations);
114    std::printf("radixSortThrust, Throughput = %.4f MElements/s, Time = %.5f s, Size = %u elements\n",
115                1.0e-6f * numElements / totalTime, totalTime, numElements);