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 |
|---|---|---|---|---|
|
sim only |
simulator.h:2706 |
||
|
sim only |
simulator.h:2742 |
||
|
sim only |
simulator.h:2734 |
||
|
sim only |
simulator.h:2735 |
||
|
sim only |
simulator.h:2695 |
||
|
sim only |
simulator.h:2683 |
||
|
sim only |
simulator.h:2724 |
||
|
sim only |
simulator.h:2745 |
||
|
sim only |
simulator.h:2707 |
||
|
sim only |
simulator.h:2749 |
||
|
sim only |
simulator.h:2723 |
||
|
sim only |
simulator.h:2744 |
||
|
sim only |
simulator.h:2717 |
||
|
sim only |
simulator.h:2718 |
||
|
sim only |
simulator.h:2753 |
||
|
sim only |
simulator.h:2737 |
||
|
sim only |
simulator.h:2736 |
||
|
sim only |
simulator.h:2693 |
||
|
sim only |
simulator.h:2684 |
||
|
sim only |
simulator.h:2688 |
||
|
sim only |
simulator.h:2691 |
||
|
sim only |
simulator.h:2689 |
||
|
sim only |
simulator.h:2690 |
||
|
sim only |
simulator.h:2685 |
||
|
sim only |
simulator.h:2692 |
||
|
sim only |
simulator.h:2686 |
||
|
sim only |
simulator.h:2696 |
||
|
sim only |
simulator.h:2697 |
||
|
sim only |
simulator.h:2698 |
||
|
sim only |
simulator.h:2719 |
||
|
sim only |
simulator.h:2720 |
||
|
sim only |
simulator.h:2743 |
||
|
sim only |
simulator.h:2700 |
||
|
Execution-policy overloads: the tag is accepted and dropped. |
sim only |
simulator.h:2739 |
|
|
sim only |
simulator.h:2701 |
||
|
sim only |
simulator.h:2740 |
||
|
sim only |
simulator.h:2708 |
||
|
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 |
|
|
sim only |
simulator.h:2702 |
||
|
sim only |
simulator.h:2703 |
||
|
sim only |
simulator.h:2741 |
||
|
sort_by_key: co-sort a values range by its keys. |
sim only |
simulator.h:2747 |
|
|
sim only |
simulator.h:2704 |
||
|
sim only |
simulator.h:2705 |
||
|
sim only |
simulator.h:2729 |
||
|
sim only |
simulator.h:2732 |
||
|
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 = ©SharedMem; 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 == © || kernel == ©SharedMem);
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);