Solver 基于OpenACC的稀疏矩阵三角求解器的正确实现

Solver 基于OpenACC的稀疏矩阵三角求解器的正确实现,solver,openacc,triangular,Solver,Openacc,Triangular,我目前正在为稀疏矩阵实现三角形解算器,并尝试使用OpenACC指令进行加速。给出了稀疏CSR格式的矩阵因子LU,OpenACC成功地解决了L因子,但与应用程序的真实解相比,U因子给出了完全错误的结果。以下是向后替换任务的加速内核代码: #pragma acc kernels deviceptr( ia, ja, factorValsU, y, x ) { for ( int idx = size; idx > 0; idx-- ) { double temp

我目前正在为稀疏矩阵实现三角形解算器,并尝试使用OpenACC指令进行加速。给出了稀疏CSR格式的矩阵因子LU,OpenACC成功地解决了L因子,但与应用程序的真实解相比,U因子给出了完全错误的结果。以下是向后替换任务的加速内核代码:

#pragma acc kernels deviceptr( ia, ja, factorValsU, y, x )
{
    for ( int idx = size; idx > 0; idx-- )
    {
        double temp = 0.0;
        int rowInit = ia[ idx - 1];
        int rowEnd  = ia[ idx ];
        #pragma acc loop vector reduction( + : temp)
        for ( int k = rowInit + 1; k < rowEnd; k++ )
        {
            temp += factorValsU[ k ] * x[ ja[ k ] ];
        }
        x[ idx ] = (y[ idx ] - temp) / factorValsU[ rowInit ];
    }
 }
U因子解算器计算错误结果的原因是内存中赋值(和讲课)的顺序吗

为完整起见,pgi18.4编译器提供的有关内核的信息如下:

triangularSolverU_acc(int, const int *, const int *, const double *, const double *, double *, bool):
614, Complex loop carried dependence of y->,x->,factorVals-> prevents parallelization
     Loop carried dependence of x-> prevents parallelization
     Loop carried backward dependence of x-> prevents vectorization
     Accelerator kernel generated
     Generating Tesla code
    614, #pragma acc loop seq
    621, #pragma acc loop vector(128) /* threadIdx.x */
         Generating reduction(+:temp)
621, Loop is parallelizable
这表明外部循环已序列化,而内部循环是一个缩减。

对于“内核”,编译器必须证明循环不包含任何依赖项,因此可以安全地并行化。但是,由于您的代码包含指针,并且指针可能被别名化到同一内存中,编译器无法证明这一点,因此,为了安全起见,无法使循环按顺序运行。要覆盖编译器分析,可以在外部for循环之前添加“#pragma acc loop independent”。“独立”是对编译器的一个断言,即循环可以安全地并行化。或者,您可以使用“并行循环”指令代替“内核”,因为“并行”意味着“独立”

对于错误答案,这通常是由于主机和设备副本之间的数据没有正确同步。您如何管理数据移动?由于您使用的是“deviceptr”,这意味着您使用的是CUDA


此外,如果您可以发布一个完整的复制示例,则更容易确定问题

是的,Mat,我的意图是外部循环是连续的,因为确实存在一个依赖循环。原则上,问题解决方案只允许还原部分的并行化。这对我来说没问题,因为它在解L因子时有效。关于数据管理,我正在使用acc_malloc+acc_memcpy_to_设备创建gpu内存区域,以便在CSR格式(ia、ja、factorVals)上传递L和U因子。要恢复解决方案,我只需从设备中执行acc_memcpy_,将结果与内存区域一起发送到主机,并进一步与我的cpu解决方案进行比较。是的,我错过了正在读取的x。您的性能将很差,因为您将利用不足的GPU,但这不是在这里的问题。我需要看一个复制的例子,以便更好地帮助理解错误答案的来源。
#pragma acc kernels deviceptr( ia, ja, factorValsL, y, x )
{
    for ( int idx = 0; idx < size; idx++ )
    {
        double temp = 0.0;
        int rowInit = ia[ idx ];
        int rowEnd  = ia[ idx + 1 ];
        #pragma acc loop vector reduction( + : temp)
        for ( int k = rowInit; k < rowEnd; k++ )
        {
            temp += factorValsL[ k ] * x[ ja[ k ] ];
        }
        x[ idx ] = y[ idx ] - temp;
    }
 }
x[ idx ] = y[ idx ] - temp     for the L factor 
x[ size - idx ] = (y[ size - idx ] - temp) / factorValsU[ rowInit ] for the U factor;
triangularSolverU_acc(int, const int *, const int *, const double *, const double *, double *, bool):
614, Complex loop carried dependence of y->,x->,factorVals-> prevents parallelization
     Loop carried dependence of x-> prevents parallelization
     Loop carried backward dependence of x-> prevents vectorization
     Accelerator kernel generated
     Generating Tesla code
    614, #pragma acc loop seq
    621, #pragma acc loop vector(128) /* threadIdx.x */
         Generating reduction(+:temp)
621, Loop is parallelizable