Skip to content

Commit 3643260

Browse files
committed
Add c++11_cuda example code.
1 parent 96f4681 commit 3643260

6 files changed

Lines changed: 65461 additions & 0 deletions

File tree

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44
[submodule "posts/american-options/external/cub"]
55
path = posts/american-options/external/cub
66
url = git://github.com/NVlabs/cub.git
7+
[submodule "c++11_cuda/cpp11-range"]
8+
path = c++11_cuda/cpp11-range
9+
url = https://github.com/harrism/cpp11-range

c++11_cuda/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
c++11_cuda : c++11_cuda.cu
2+
nvcc -Icpp11-range --std=c++11 c++11_cuda.cu -o c++11_cuda

c++11_cuda/c++11_cuda

461 KB
Binary file not shown.

c++11_cuda/c++11_cuda.cu

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#include <thrust/device_ptr.h>
2+
#include <thrust/count.h>
3+
#include <thrust/execution_policy.h>
4+
5+
#include <iostream>
6+
7+
/////////////////////////////////////////////////////////////////
8+
// Some utility code to define grid_stride_range
9+
// Normally this would be in a header but it's here
10+
// for didactic purposes. Uses
11+
#include "range.hpp"
12+
using namespace util::lang;
13+
14+
// type alias to simplify typing...
15+
template<typename T>
16+
using step_range = typename range_proxy<T>::step_range_proxy;
17+
18+
template <typename T>
19+
__device__
20+
step_range<T> grid_stride_range(T begin, T end) {
21+
begin += blockDim.x * blockIdx.x + threadIdx.x;
22+
return range(begin, end).step(gridDim.x * blockDim.x);
23+
}
24+
/////////////////////////////////////////////////////////////////
25+
26+
template <typename T, typename Predicate>
27+
__device__
28+
void count_if(int *count, T *data, int n, Predicate p)
29+
{
30+
for (auto i : grid_stride_range(0, n)) {
31+
if (p(data[i])) atomicAdd(count, 1);
32+
}
33+
}
34+
35+
// Use count_if with a lambda function that searches for x, y, z or w
36+
// Note the use of range-based for loop and initializer_list inside the functor
37+
// We use auto so we don't have to know the type of the functor or array
38+
__global__
39+
void xyzw_frequency(int *count, char *text, int n)
40+
{
41+
const char letters[] { 'x','y','z','w' };
42+
43+
count_if(count, text, n, [&](char c) {
44+
for (const auto x : letters)
45+
if (c == x) return true;
46+
return false;
47+
});
48+
}
49+
50+
__global__
51+
void xyzw_frequency_thrust_device(int *count, char *text, int n)
52+
{
53+
const char letters[] { 'x','y','z','w' };
54+
55+
auto ptext = thrust::device_pointer_cast(text);
56+
57+
*count = thrust::count_if(thrust::device, ptext, ptext+n, [&](char c) {
58+
for (const auto x : letters)
59+
if (c == x) return true;
60+
return false;
61+
});
62+
}
63+
64+
// a bug in Thrust 1.8 causes warnings when this is uncommented
65+
// so commented out by default -- fixed in Thrust master branch
66+
#if 0
67+
void xyzw_frequency_thrust_host(int *count, char *text, int n)
68+
{
69+
const char letters[] { 'x','y','z','w' };
70+
71+
*count = thrust::count_if(thrust::host, text, text+n, [&](char c) {
72+
for (const auto x : letters)
73+
if (c == x) return true;
74+
return false;
75+
});
76+
}
77+
#endif
78+
79+
int main(int argc, char** argv)
80+
{
81+
const char *filename = "warandpeace.txt";
82+
83+
int numBytes = 16*1048576;
84+
char *h_text = (char*)malloc(numBytes);
85+
86+
char *d_text;
87+
cudaMalloc((void**)&d_text, numBytes);
88+
89+
FILE *fp = fopen(filename, "r");
90+
int len = fread(h_text, sizeof(char), numBytes, fp);
91+
fclose(fp);
92+
std::cout << "Read " << len << " byte corpus from " << filename << std::endl;
93+
94+
cudaMemcpy(d_text, h_text, len, cudaMemcpyHostToDevice);
95+
96+
int count = 0;
97+
int *d_count;
98+
cudaMalloc(&d_count, sizeof(int));
99+
cudaMemset(d_count, 0, sizeof(int));
100+
101+
// Try uncommenting one kernel call at a time
102+
xyzw_frequency<<<8, 256>>>(d_count, d_text, len);
103+
//xyzw_frequency_thrust_device<<<1, 1>>>(d_count, d_text, len);
104+
cudaMemcpy(&count, d_count, sizeof(int), cudaMemcpyDeviceToHost);
105+
106+
//xyzw_frequency_thrust_host(&count, h_text, len);
107+
108+
std::cout << "counted " << count << " instances of 'x', 'y', 'z', or 'w' in \""
109+
<< filename << "\"" << std::endl;
110+
111+
cudaFree(d_count);
112+
cudaFree(d_text);
113+
114+
return 0;
115+
}

c++11_cuda/cpp11-range

Submodule cpp11-range added at 70f8449

0 commit comments

Comments
 (0)