Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Cuda 相对较小阵列尺寸的GPU精度问题?_Cuda_Precision - Fatal编程技术网

Cuda 相对较小阵列尺寸的GPU精度问题?

Cuda 相对较小阵列尺寸的GPU精度问题?,cuda,precision,Cuda,Precision,我有一些CUDA代码,它做了一些线性代数来反转一种特殊类型的结构化矩阵。我使用该算法的序列化版本的结果计算RMS错误。错误会随着问题的大小而增长,达到我预期的更大程度。有人能解释为什么会出现这种情况吗 GPU代码非常幼稚。这是有意的,我会很快优化它-我只是想要一个简单的基线内核,提供适当的结果 __global__ void levinson_durbin_gpu(TYPE *h0_d, TYPE *h_d, TYPE *v_d, TYPE *x_d, TYPE *y_d, int N) //

我有一些CUDA代码,它做了一些线性代数来反转一种特殊类型的结构化矩阵。我使用该算法的序列化版本的结果计算RMS错误。错误会随着问题的大小而增长,达到我预期的更大程度。有人能解释为什么会出现这种情况吗

GPU代码非常幼稚。这是有意的,我会很快优化它-我只是想要一个简单的基线内核,提供适当的结果

 __global__ void levinson_durbin_gpu(TYPE *h0_d, TYPE *h_d, TYPE *v_d, TYPE *x_d, TYPE *y_d, int N) //Naive kernel
{
    int j = threadIdx.x;
    int i;

    __shared__ TYPE hn_1[512]; 
    hn_1[j] = h_d[j];

    for(i=1; i<N; i++)
    {
        if(j < i)
        {
            TYPE hn = h_d[i];
            TYPE yn = y_d[i];

            __syncthreads();

            //Set up temporary arrays, compute inner products
            __shared__ TYPE temp[512]; //Temp for hn_1_J_v
            __shared__ TYPE temp2[512]; //Temp for hn_1_J_x
            __shared__ TYPE temp3[512]; //Temp for hn_1_v

            temp[j] = hn_1[j]*v_d[i-j-1];
            temp2[j] = hn_1[j]*x_d[i-j-1];
            temp3[j] = hn_1[j]*v_d[j];
            __syncthreads();

            //Three reductions at once
            for(unsigned int s=1; s<i; s*=2)
            {
                int index = 2*s*j;
                if((index+s) < i)
                {
                    temp[index] += temp[index+s];
                    temp2[index] += temp2[index+s];
                    temp3[index] += temp3[index+s];
                }
                __syncthreads();
            }

            TYPE hn_1_J_v = temp[0];
            TYPE hn_1_J_x = temp2[0];
            TYPE hn_1_v = temp3[0];

            TYPE alpha_v = (hn - hn_1_J_v)/(h0_d[0] - hn_1_v);
            TYPE alpha_x = (yn - hn_1_J_x)/(h0_d[0] - hn_1_v);

            __shared__ TYPE w_v[512];
            w_v[j] = v_d[j] - alpha_v*v_d[i-j-1];

            __shared__ TYPE w_x[512];
            w_x[j] = x_d[j] - alpha_x*v_d[i-j-1];

            v_d[j] = w_v[j];
            x_d[j] = w_x[j];
            if(j == 0)
            {
                v_d[i] = alpha_v;
                x_d[i] = alpha_x;
            }


        }

        __syncthreads();
    }

}
\uuuuu global\uuuuu void levinson\u durbin\u gpu(类型*h0\u d,类型*h\u d,类型*v\u d,类型*x\u d,类型*y\u d,int N)//朴素内核
{
int j=螺纹IDX.x;
int i;
__共享_uuu类型hn_u1[512];
hn_1[j]=h_d[j];

因为(i=1;i多亏了评论部分的帮助,我才能够自己解决这个问题,所以我将在这里记录下来,以防其他人遇到类似的问题

问题确实是同步问题-我在发散控制流块中使用了
\uu syncthreads()
。解决方案是将该控制流块分成多个部分,并在每个部分后调用
\uu syncthreads()

__global__ void levinson_durbin_gpu(TYPE *h0_d, TYPE *h_d, TYPE *v_d, TYPE *x_d, TYPE *y_d, int N) //Naive kernel
{
    int j = threadIdx.x;
    int i;

    __shared__ TYPE hn_1[512];
    hn_1[j] = h_d[j];
    __syncthreads();

    //Set up temporary arrays
    __shared__ TYPE temp[512]; //Temp for hn_1_J_v
    __shared__ TYPE temp2[512]; //Temp for hn_1_J_x
    __shared__ TYPE temp3[512]; //Temp for hn_1_v

    TYPE hn;
    TYPE yn;

    for(i=1; i<N; i++)
    {
        if(j < i)
        {
            hn = h_d[i];
            yn = y_d[i];

            //Compute inner products
            temp[j] = hn_1[j]*v_d[i-j-1];
            temp2[j] = hn_1[j]*x_d[i-j-1];
            temp3[j] = hn_1[j]*v_d[j];
        }

        __syncthreads();

        //Have all threads complete this section to avoid synchronization issues

        //Three reductions at once
        for(unsigned int s=1; s<i; s*=2)
        {
            int index = 2*s*j;
            if((index+s) < i)
            {
                temp[index] += temp[index+s];
                temp2[index] += temp2[index+s];
                temp3[index] += temp3[index+s];
            }
            __syncthreads();
        }

        if(j < i)
        {
            TYPE hn_1_J_v = temp[0];
            TYPE hn_1_J_x = temp2[0];
            TYPE hn_1_v = temp3[0];

            TYPE alpha_v = (hn - hn_1_J_v)/(h0_d[0] - hn_1_v);
            TYPE alpha_x = (yn - hn_1_J_x)/(h0_d[0] - hn_1_v);

            __shared__ TYPE w_v[512];
            w_v[j] = v_d[j] - alpha_v*v_d[i-j-1];

            __shared__ TYPE w_x[512];
            w_x[j] = x_d[j] - alpha_x*v_d[i-j-1];

            v_d[j] = w_v[j];
            x_d[j] = w_x[j];
            if(j == 0)
            {
                v_d[i] = alpha_v;
                x_d[i] = alpha_x;
            }
        }

    __syncthreads();
}

}
\uuuuu global\uuuuu void levinson\u durbin\u gpu(类型*h0\u d,类型*h\u d,类型*v\u d,类型*x\u d,类型*y\u d,int N)//朴素内核
{
int j=螺纹IDX.x;
int i;
__共享_uuu类型hn_u1[512];
hn_1[j]=h_d[j];
__同步线程();
//设置临时数组
__共享的uuuuuuuuu类型临时[512];//hn_1_J_v的临时
__共享的uuu类型temp2[512];//hn_1_J_x的Temp
__共享的uuu类型temp3[512];//hn_1_v的Temp
hn型;
yn型;

对于(i=1;这可能与精度无关,而与缓冲区溢出有关。如果没有完整的复制案例来研究,很难猜测可能会出现什么问题,但我会非常怀疑
index=2*s*j
。如果我正确地阅读了代码,对于你的N=80示例,你可以得到i=79,j=78 w这将给出s=64和index=2*64*78=9984,这是一个很大的缓冲区溢出。您确认没有API错误并尝试使用cuda memcheck运行代码了吗?感谢您的回复@talonmies。我已经确认没有API错误,但我还没有使用cuda memcheck,我很快就会这样做。只是想弄清楚,为什么这样的缓冲区会溢出流正在发生?请注意,我只在
(index+s)
时访问临时数组,因此在您的示例中,我只通过
temp[79]
访问
temp[0]
,因为
N=80
@Adam27X:调用syncthreads()时,条件分支“if(jI+1
取决于循环迭代
I
的结果,所以我确实需要某种障碍。。。