【问题标题】:How std::vectors within loop in OpenACC?如何在 OpenACC 中循环内的 std::vectors?
【发布时间】:2020-11-06 17:56:52
【问题描述】:

我有以下代码

int main(int argc, char** argv )
{
    std::vector< std::vector< std::vector<double> > > vec { 
        {{1,2},{3,4}, {5,6},{7,8}}, 
        {{9,10}, {11,12}}, 
        {{13,14}, {15,16}, {17,18}} };

    #pragma acc parallel loop
    for (int k = 0; k <3; k++) {

        std::vector<std::vector<double>>& vec2d = vec[k];
        int L = vec2d.size();

        //std::vector<int>dVec{67,51,1,0,50};
        std::vector<double>dVec(L, 0.0);

        for (int i = 0; i < L; i++)
        {
            dVec[i] = vec2d[i][1] - vec2d[i][0];
        }

        for (int j=0; j<2; j++) {
            printf("k: %d j: %d vec0: %f, vec1: %f\n", k, j, vec2d[j][0], vec2d[j][1]);
        }
    }
    std::cout<<"finished\n";

    return 0;
}

我用pgc++ -fast -ta=tesla:cuda9.2,managed -o runEx runEx.cpp -std=c++17 &amp;&amp; ./runEx编译

如果我注释掉#pragma acc parallel loop,那么它就可以工作。但是如果我把它留在那里,那么我会得到错误

PGCC-S-0155-Procedures called in a compute region must have acc routine information: operator delete (void *) (runEx.cpp: 425)
PGCC-S-0155-Accelerator region ignored; see -Minfo messages  (runEx.cpp: 6)
PGCC/x86-64 Linux 19.10-0: compilation completed with severe errors

另外,如果我注释掉 std::vector&lt;int&gt;dVec 和包含它的 for 循环,那么即使使用 #pragma acc parallel loop,代码也可以工作

但是,如果我改变循环,它就变成了:

#pragma acc parallel loop
for (int k = 0; k <3; k++) {
    std::vector<int>dVec{67,51,1,0,50};
}

然后我得到同样的错误

这是为什么?

【问题讨论】:

    标签: c++ openacc


    【解决方案1】:

    来自网站:https://docs.computecanada.ca/wiki/OpenACC_Tutorial_-_Optimizing_loops

    我也能看到东西:

    1. 您的声明:
    #pragma acc parallel loop
    

    缺少参数。

    1. 站点调用函数时使用:#pragma acc 并行循环存在(row_offsets,cols,Acoefs,xcoefs,ycoefs) 这意味着参数为 0 的函数可能是非法的。

    【讨论】:

      【解决方案2】:

      这里的问题是 std::vector 有一些在设备上不可用的成员函数。编译错误是专门调出delete,但是我怀疑size这个函数也会有问题,构造函数也一样。由于您不控制std::vector 的来源,因此您无法向它们添加acc routine。我过去所做的解决方法是在 OpenACC 区域之外严格使用向量,并将指向其数据的原始指针传递到区域中。这肯定很麻烦,尤其是对于大型代码,但它确实有效。否则,您也可以尝试实现自己的最小向量类,该类使用acc routine 装饰成员函数。我也看到这个成功了。

      对于一个非常大的 L,您可以通过将 acc parallel loop 单独放在您的 i 循环中来获得,但除非您将数组提升到 @ 之外,否则您将大量来回复制数据987654328@ 循环以启用重用。

      【讨论】:

      • 那么为什么 std::vector 对std::vector&lt;std::vector&lt;double&gt;&gt;&amp; vec2d = vec[k]; 有效?如果我保留它但注释掉 dVec,那么 OpenACC 代码可以正常工作
      • 如何在 OpenACC 区域之外使用dVec?我需要它的大小取决于vec2d,我需要在 OpenACC 区域内
      • "那么为什么 std::vector 对 std::vector 起作用<:vector>>& vec2d = vec[k];" - 我认为这是因为它是对另一个向量的引用,它进行了实际分配等。另一方面,dVec 在循环中被创建和删除。您可能希望将其分配给最大预期大小。我让它像这样运行,但是你需要私有化 dVec 以获得相同的行为,那时我又开始遇到错误。如果我将 dVec 声明为循环内的普通静态数组,我可以让它工作。
      猜你喜欢
      • 2020-08-14
      • 2021-09-23
      • 2015-10-22
      • 2021-04-24
      • 1970-01-01
      • 2015-04-17
      • 1970-01-01
      • 1970-01-01
      • 2018-09-23
      相关资源
      最近更新 更多