I am having troubles understanding a bug that I have in a simple Cuda kernel. I shrinked down my kernel to the minimum that still shows the error.
I have a "Polygon" class that just stores a number of points. I have a function that "adds a point" (just increments the counter), and I add 4 points to all polygons in my array of polygons. Finally, I call a function that updates the number of points using a loop. If, in this loop, I call new_nbpts++ once, I obtain the expected answer : all polygons have 4 points. If in the same loop I call new_nbpts++ a second time, then my polygons have a garbage number of points (4194304 points) which is not correct (I should get 8).
I expect there is something I misunderstood though.
Complete kernel:
#include <stdio.h>
#include <cuda.h>
class Polygon {
public:
__device__ Polygon():nbpts(0){};
__device__ void addPt() {
nbpts++;
};
__device__ void update() {
int new_nbpts = 0;
for (int i=0; i<nbpts; i++) {
new_nbpts++;
new_nbpts++; // calling that a second time screws up my result
}
nbpts = new_nbpts;
}
int nbpts;
};
__global__ void cut_poly(Polygon* polygons, int N)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx>=N) return;
Polygon pol;
pol.addPt();
pol.addPt();
pol.addPt();
pol.addPt();
for (int i=0; i<N; i++) {
pol.update();
}
polygons[idx] = pol;
}
int main(int argc, unsigned char* argv[])
{
const int N = 20;
Polygon p_h[N], *p_d;
cudaError_t err = cudaMalloc((void **) &p_d, N * sizeof(Polygon));
int block_size = 4;
int n_blocks = N/block_size + (N%block_size == 0 ? 0:1);
cut_poly <<< n_blocks, block_size >>> (p_d, N);
cudaMemcpy(p_h, p_d, sizeof(Polygon)*N, cudaMemcpyDeviceToHost);
for (int i=0; i<N; i++)
printf("%d\n", p_h[i].nbpts);
cudaFree(p_d);
return 0;
}