此问题与我几周前发布的现有问题有关:TERCOM algorithm - Changing from single thread to multiple threads in CUDA
简要解释一下,内核中的每个线程计算一个MAD值,我想知道最小值及其位置。
我试图像这样使用atomicMin
__global__ void kernel (int m, int n, int h, int N, int *f, float heading, float *measurements, int *global_min)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
int idy = blockIdx.y * blockDim.y + threadIdx.y;
float MAD=0;
float pos[2];
float theta=heading*(PI/180);
float fval = 0;
// Calculate how much to move in x and y direction
float offset_x = h*cos(theta);
float offset_y = -h*sin(theta);
//Calculate Mean Absolute Difference
if(idx < n && idy < m)
{
for(float g=0; g<N; g++)
{
float fval = tex2D (tex, idx+(g-2)*offset_x+0.5f, idy+(g-2)*offset_y+0.5f);
MAD += abs(measurements[(int)g]-fval);
}
}
cuPrintf("%.2f \n",MAD);
atomicMin(global_min, MAD);
pos[0]=idx;
pos[1]=idy;
f[0]=*global_min;
f[1]=pos[0];
f[2]=pos[1];
}
它产生了正确的结果,但atomicMin无法找到最小值的位置。
我也尝试使用推力库
__global__ void kernel (int m, int n, int h, int N, int *f, float heading, float *measurements, int *global_min, float *dev_MAD)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
int idy = blockIdx.y * blockDim.y + threadIdx.y;
float theta=heading*(PI/180);
float fval = 0;
// Calculate how much to move in x and y direction
float offset_x = h*cos(theta);
float offset_y = -h*sin(theta);
//Calculate Mean Absolute Difference
if(idx < n && idy < m)
{
for(float g=0; g<N; g++)
{
float fval = tex2D (tex, idx+(g-2)*offset_x+0.5f, idy+(g-2)*offset_y+0.5f);
*dev_MAD += abs(measurements[(int)g]-fval);
}
}
cuPrintf("%.2f \n",MAD);
}
像这样调用内核
kernel <<< dimGrid,dimBlock >>> (m, n, h, N, dev_results, heading, dev_measurements, global_min, dev_MAD);
thrust::device_ptr<float> dev_ptr(dev_MAD);
thrust::device_ptr<float> min_pos = thrust::min_element(dev_ptr, dev_ptr + n*m);
int abs_pos = min_pos - dev_ptr;
float min_val=min_pos[0];
cudaMemcpy(&min_val, dev_MAD+abs_pos, sizeof(float), cudaMemcpyDeviceToHost);
// Print out the result
printf("Min=%.2f pos=%d\n",min_val,abs_pos);
但是这个程序打印出来:Min = -207521258711807190000000000000000000000.00 pos = 0
我已经查看了许多缩减示例,但似乎每个人都将值存储在数组中,而不是存储在每个单独的线程中。
所以问题:
答案 0 :(得分:0)
对于您的Thrust代码,您正在写入dev_MAD [0],但计算结果就像您已写入整个数组一样。
IIUC,你试图找到最小值和相应的位置,你在每个线程中将值作为变量但不存储在内存中。
我可以通过几种简单的方法来做到这一点,但都涉及将值存储到内存中并计算第二遍中的最小/位置。
首先,你可以像你已经尝试过的那样使用Thrust的min_element,但你可以将值存储到内核中的device_vector,然后独立调用thrust :: min_element。 p>
其次,您可以先通过计算线程块中的最小/位置来节省一些内存空间和带宽(然后再使用thrust :: min_element)。为此,您可以使用自定义reduce运算符进行CUB缩减(比较值,数据为{value,index})。