Algorithm OpenCL-Cholesky分解

Algorithm OpenCL-Cholesky分解,algorithm,opencl,blas,Algorithm,Opencl,Blas,我使用OpenCL实现了以下Cholesky分解算法。代码表现出随机行为。它只与cpu输出匹配几次。有人能帮我找出我的实现有什么问题吗 以下是算法: procedure CHOLESKY(A) int i, j, k; for k := 0 to n − 1 do /* 1st loop */ /* Obtain the square root of the diagonal element. */ A[k, k] := A[k, k]; for j := k + 1

我使用OpenCL实现了以下Cholesky分解算法。代码表现出随机行为。它只与cpu输出匹配几次。有人能帮我找出我的实现有什么问题吗

以下是算法:

procedure CHOLESKY(A)
int i, j, k;
for k := 0 to n − 1 do /* 1st loop */
    /* Obtain the square root of the diagonal element. */
    A[k, k] := A[k, k];

    for j := k + 1 to n − 1 do /* 2nd loop */
    /* The division step. */
        A[k, j] := A[k, j]/A[k, k];
    end for

    for i := k + 1 to n − 1 do /* 3rd loop */
        for j := i to n − 1 do /* 4th loop */
            /* The elimination step. */
            A[i, j] := A[i, j] - A[k, i] × A[k, j];

        end for
    end for
end for
将上述算法并行化的方法:

从算法来看,消除步骤是最昂贵的。所以我有最外层的环 在主机代码中,我在循环中调用内核。内核的一次运行 对应于第三个循环的单个迭代。因此,我启动了(n-1)-(k+1)+1工作组。工作组中的工作项数设置为n/2。第二个for循环也是在内核中计算的,但是我只允许第一个工作组来做

相关主机代码

// for a 10 X 10 matrix, MATRIX_SIZE = 10
localWorkSize[0] = MATRIX_SIZE/2;
stride = MATRIX_SIZE/2;
cl_event             event;

for(k = 0; k < MATRIX_SIZE; k++)
{

    int isize = (MATRIX_SIZE-1) - (k+1) + 1;
    int num_blocks = isize;
    if(num_blocks <= 0)
            num_blocks = 1;
    globalWorkSize[0] = num_blocks * WA/2;

    errcode = clSetKernelArg(clKernel, 0, sizeof(int), (void *)&k);
    errcode |= clSetKernelArg(clKernel, 1, sizeof(cl_mem), (void *)&d_A);
    errcode |= clSetKernelArg(clKernel, 2, sizeof(int), (void *)&stride);

    errcode = clEnqueueNDRangeKernel(clCommandQueue,
          clKernel, 1, NULL, globalWorkSize,
          localWorkSize, 0, NULL, &event);

    OpenCL_CheckError(errcode, "clEnqueueNDRangeKernel");
    clFinish(clCommandQueue);
}
__kernel void
batchedCholesky(__global float *U, int k, int stride)
{

    int tx = get_global_id(0);
    unsigned int j;
    unsigned int num_rows = MATRIX_SIZE;

    if(tx==0)
    {
            // Take the square root of the diagonal element
            U[k * num_rows + k] = sqrt(U[k * num_rows + k]);
    }
    barrier(CLK_GLOBAL_MEM_FENCE);

    int offset = (k+1); //From original loop
    int jstart = get_local_id(0) + offset;
    int jstep = stride;
    int jtop = num_rows - 1;

    int jbottom = (k + 1);
    //Do work for this i iteration
    //Division step
    if(get_group_id(0) == 0)
    {
            for(j = jstart; (j >= jbottom) && (j <= jtop); j+=jstep)
            {
                    U[k * num_rows + j] /= U[k * num_rows + k]; // Division step
            }
    }
    barrier(CLK_GLOBAL_MEM_FENCE);

    j = 0;

    int i = get_group_id(0) + (k+1);

    offset = i;

    jstart = get_local_id(0) + offset;

    jbottom = i;

    for( j = jstart; j >= jbottom && j <= jtop; j += jstep)

            U[i * num_rows + j] -= U[k * num_rows + i] * U[k * num_rows + j];

    barrier(CLK_GLOBAL_MEM_FENCE);   
}
//对于10 X 10矩阵,矩阵大小=10
localWorkSize[0]=矩阵大小/2;
步幅=矩阵大小/2;
cl_事件;
对于(k=0;k如果(num_blocks=jbottom)&&(j=jbottom&&j不是所有工作项都同时执行,它们可能会成批运行。因此,在
CLK\u GLOBAL\u MEM\u FENCE
之前运行的代码不会包含所有值。这可能是错误的根源


如果您需要全局同步,请使用多个内核。

我看到了三个
CLK\u LOCAL\u MEM\u FENCE
障碍,但没有使用本地内存。您的意思是
CLK\u global\u MEM\u FENCE
?还是这不是全部相关代码?是的,这是正确的。应该是CLK\u global\u MEM\u FENCE。我找不到任何说明如何使用mu的示例多个内核。你能提供一个吗?很好。我让它工作了。你关于全局同步的观察是正确的。谢谢。