CUDA:sum-reduction ---调用设备功能时丢失的数据

时间:2013-06-13 04:14:00

标签: cuda parallel-processing gpu-programming

我正在编写一个CUDA和减少代码,它采用从元素begin_index到end_index开始的数组绝对值的总和(我使用一个具有可变数量线程的块)。但是,当我将数组A传递给reduce_fabs()时,来自A[4]和更高索引的所有内容最终都会被设置为零。这是代码和函数调用以及我尝试过的更多解释。

这个调用sum-reduction内核的内核:

__device__ void tridiag(float *A,int *dim, float *diag,float *offdiag) {

    A[0] = 1.0f; A[1] = 2.0f; A[2] = 3.0f;
    A[3] = 4.0f; A[4] = 5.0f; A[5] = 6.0f;
    diag[0] = reduce_fabs(A,0,3);
    __syncthreads();
    diag[1] = reduce_fabs(A,0,4);

    return;
}

这是总和减少内核:

__device__ float reduce_fabs(float *v, int begin_index, int end_index) {
    extern __shared__ float sum_array[];
    int tid = threadIdx.x;
    if(tid >= begin_index && tid <= end_index) {
        sum_array[tid-begin_index] = fabs(v[tid]);
        sum_array[tid+end_index-begin_index+1] = 0;
    }
    __syncthreads();
    for(int j=1;j<=(end_index-begin_index);j*=2) {
        if((tie-begin_index)%(2*j) == 0 && tie >= begin_index && tid <= end_index) {
            sum_array[(tie-begin_index)] += sum_array[(tie-begin_index)+j];
        }
        __syncthreads();
    }

    return sum_array[0];
}

看过代码之后,问题的一个更具体的描述是,当我将数组A传递给reduce_fabs()时,元素4的值变为A[4] = 0,这是错误的。 A[0]A[1]A[2]A[3]适用于任何end_index,但每个end_index大于3会产生A的元素通过减少内核后,超过3的{1}}被设置为零。

以下是我的尝试:

  • 我尝试diag[0] = A[4]以确保初始分配正常。是的。
  • 我删除了reduce_fabs()的求和部分,在第一个__syncthreads()之后停止,问题仍然存在。
  • 我消除了元素归零以外的元素归零;即我评论//sum_array[tid+end_index-begin_index+1] = 0(总结也被注释掉了这一部分)。没有成功。
  • 我删除了if(tie >= begin_index && tid <= end_index),以便为所有主题分配sum_array(总结也被注释掉)无济于事。

这是运行它的主要功能:

#include<stdio.h>
#include<stdlib.h>
#include<cuda.h>

int main() {
    int n = 10;
    float *A = (float *)malloc(n*sizeof(*A));
    float *diag = (float *)malloc(n*sizeof(*A));
    float *offdiag = (float *)malloc(n*sizeof(*A));

    int *p_n;
    float *p_A, *p_diag, *p_offdiag;

    cudaMalloc((void**) &p_A,n*sizeof(float));
    cudaMalloc((void**) &p_diag,n*sizeof(float));
    cudaMalloc((void**) &p_offdiag,n*sizeof(float));
    cudaMalloc((void**) &p_n,sizeof(int));

    cudaMemcpy(p_n,&n,n*sizeof(int),cudaMemcpyHostToDevice);

    tridiag<<<1,n>>>(p_A,p_n,p_diag,p_offdiag);

    cudaMemcpy(A,p_A,n*sizeof(float),cudaMemcpyDeviceToHost);
    cudaMemcpy(diag,p_diag,n*sizeof(float),cudaMemcpyDeviceToHost);

    printf("A[0] = %f  A[1] = %f  A[2] = %f\n",A[0],A[1],A[2]);
    printf("A[3] = %f  A[4] = %f  A[5] = %f\n",A[3],A[4],A[4]);
    printf("diag[0] = %f  diag[1] = %f\m",diag[0],diag[1]);

    cudaFree(p_A);
    cudaFree(p_diag);
    cudaFree(p_offdiag);
    free(A);
    free(diag);
    free(offdiag);

    return 0;
}

0 个答案:

没有答案