Skip to content

Commit 211d8f5

Browse files
authored
Merge pull request #6 from SimeonEhrig/random2Dmatrix
2 parents 2a5418d + 89008d0 commit 211d8f5

File tree

2 files changed

+181
-0
lines changed

2 files changed

+181
-0
lines changed

examples/basic/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,13 @@ target_sources(${_TARGET_ANNOTATED}
2222
set_target_properties(${_TARGET_ANNOTATED} PROPERTIES
2323
CUDA_CXX_STANDARD 17
2424
)
25+
26+
set(_TARGET_RANDOM_2D_MATRIX random2dMatrix)
27+
28+
add_executable(${_TARGET_RANDOM_2D_MATRIX})
29+
target_sources(${_TARGET_RANDOM_2D_MATRIX}
30+
PRIVATE
31+
random2dMatrix.cu)
32+
set_target_properties(${_TARGET_RANDOM_2D_MATRIX} PROPERTIES
33+
CUDA_CXX_STANDARD 17
34+
)

examples/basic/random2dMatrix.cu

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
// The applicaiton creates a 2D matrix and initialize each element randomly with a value between 0 and 10.
2+
// The kernel is simply decrementing each element until 0 in a very ineffective way.
3+
4+
#include <iostream>
5+
#include <vector>
6+
#include <random>
7+
#include <algorithm>
8+
9+
// The wrapper macro is required, that __LINE__ is correct pointing to the line, where the check fails
10+
#define checkCudaError(ans) \
11+
{ \
12+
checkCudaErrorFunc((ans), __FILE__, __LINE__); \
13+
}
14+
15+
inline void checkCudaErrorFunc(cudaError_t err, const char *file, int line)
16+
{
17+
if (err != cudaSuccess)
18+
{
19+
std::cout << "\r" << file << ":" << line << " -> Cuda Error " << err << ": " << cudaGetErrorString(err) << std::endl;
20+
std::cout << "Aborting..." << std::endl;
21+
exit(0);
22+
}
23+
}
24+
25+
__global__ void decrement(unsigned int const size, unsigned int *data, unsigned int *control)
26+
{
27+
int index = threadIdx.x + blockIdx.x * blockDim.x;
28+
int stride = blockDim.x * gridDim.x;
29+
30+
for (int i = index; i < size; i += stride)
31+
{
32+
while (data[i] > 0)
33+
{
34+
data[i] = data[i] - 1;
35+
control[i] = control[i] + 1;
36+
}
37+
}
38+
}
39+
40+
/// @brief Increment all values in a specific area by the value of increment. The maximum value of an entry is clamp to 10.
41+
/// @param data Data to increment.
42+
/// @param dim Dimensions of the 2D matrix.
43+
/// @param y_start Y start coordinate of the area to increment.
44+
/// @param x_start X start coordinate of the area to increment.
45+
/// @param size Size of the Y and X direction of the area to increment.
46+
/// @param increment Value to increment.
47+
void hot_spot(std::vector<unsigned int> &data, unsigned int const dim, unsigned int const y_start, unsigned int const x_start, unsigned int const size, unsigned int const increment)
48+
{
49+
for (auto y = y_start; y < y_start + size; ++y)
50+
{
51+
for (auto x = x_start; x < x_start + size; ++x)
52+
{
53+
if (data[y * dim + x] + increment > 10)
54+
{
55+
data[y * dim + x] = 10;
56+
}
57+
else
58+
{
59+
data[y * dim + x] += increment;
60+
}
61+
}
62+
}
63+
}
64+
65+
int main(int argc, char **argv)
66+
{
67+
unsigned int dim = 100;
68+
69+
std::vector<unsigned int> h_data(dim * dim);
70+
// create a 2D matrix where all elements are 0
71+
std::vector<unsigned int> h_control(dim * dim, 0);
72+
73+
// initialize data matrix with random numbers betweem 0 and 10
74+
std::uniform_int_distribution<unsigned int> distribution(
75+
0,
76+
10);
77+
std::default_random_engine generator;
78+
std::generate(
79+
h_data.begin(),
80+
h_data.end(),
81+
[&distribution, &generator]()
82+
{ return distribution(generator); });
83+
84+
// enable me, to create a hot spot area
85+
// the hot spot area should looks interessting in the memory access visualization
86+
if (false)
87+
{
88+
hot_spot(h_data, dim, 8, 10, 10, 3);
89+
}
90+
91+
// enable me, to print the matrix
92+
if (false)
93+
{
94+
for (auto y = 0; y < dim; ++y)
95+
{
96+
for (auto x = 0; x < dim; ++x)
97+
{
98+
if (h_data[y * dim + x] < 10)
99+
{
100+
std::cout << " " << h_data[y * dim + x] << " ";
101+
}
102+
else
103+
{
104+
std::cout << h_data[y * dim + x] << " ";
105+
}
106+
}
107+
std::cout << std::endl;
108+
}
109+
}
110+
111+
unsigned int *d_data = nullptr;
112+
unsigned int *d_control = nullptr;
113+
114+
size_t const buffer_size_byte = sizeof(unsigned int) * dim * dim;
115+
116+
checkCudaError(cudaMalloc((void **)&d_data, buffer_size_byte));
117+
checkCudaError(cudaMalloc((void **)&d_control, buffer_size_byte));
118+
119+
checkCudaError(cudaMemcpy(d_data, h_data.data(), buffer_size_byte, cudaMemcpyHostToDevice));
120+
// copy h_controll to initialize all values with 0 on the GPU
121+
checkCudaError(cudaMemcpy(d_control, h_control.data(), buffer_size_byte, cudaMemcpyHostToDevice));
122+
123+
// change me and look, how the visulization looks like
124+
int const blockSize = 32;
125+
int const numBlocks = ((dim * dim) + blockSize - 1) / blockSize;
126+
127+
decrement<<<numBlocks, blockSize>>>(dim * dim, d_data, d_control);
128+
checkCudaError(cudaGetLastError());
129+
130+
checkCudaError(cudaMemcpy(h_control.data(), d_control, buffer_size_byte, cudaMemcpyDeviceToHost));
131+
132+
bool success = true;
133+
134+
for (auto y = 0; y < dim; ++y)
135+
{
136+
for (auto x = 0; x < dim; ++x)
137+
{
138+
if (h_control[y * dim + x] != h_data[y * dim + x])
139+
{
140+
std::cout << "h_control[" << y << ", " << x << "] != h_data[" << y << ", " << x << "]" << std::endl;
141+
std::cout << h_control[y * dim + x] << " != " << h_data[y * dim + x] << std::endl;
142+
success = false;
143+
}
144+
}
145+
}
146+
147+
checkCudaError(cudaMemcpy(h_data.data(), d_data, buffer_size_byte, cudaMemcpyDeviceToHost));
148+
149+
for (auto y = 0; y < dim; ++y)
150+
{
151+
for (auto x = 0; x < dim; ++x)
152+
{
153+
if (h_data[y * dim + x] != 0)
154+
{
155+
std::cout << "h_data[" << y << ", " << x << "] != 0" << std::endl;
156+
std::cout << "value is: " << h_data[y * dim + x] << std::endl;
157+
success = false;
158+
}
159+
}
160+
}
161+
162+
if (success)
163+
{
164+
std::cout << "The kernel worked correctly" << std::endl;
165+
}
166+
167+
checkCudaError(cudaFree(d_data));
168+
checkCudaError(cudaFree(d_control));
169+
170+
return 0;
171+
}

0 commit comments

Comments
 (0)