我正在尝试在gpu上复制向量数组的向量。
我尝试使用OpenACC Copyin子句。CopyIn子句并未复制我数组的所有基础数据。当我尝试访问底层矢量数据时,我在运行时会发现"非法地址访问"错误。
vector<int32_t> *k1p = new vector<int32_t>[bin_num];
for (int i = 0; i < bin_mum; i++) {
//......
k1p[i].push_back(i);
}
#pragma acc kernels loop independent copyin(k1p[0:bin_num])
for (int i = 0; i < bin_mum; i++) {
//........
for (vector<int32_t>::const_iterator i2_it=k1p[i].begin(); i2_it!=k1p[i].end(); i2_it++) {
//.......
}
//..........
}
我想访问基础向量K1P [i]的元素,但实际上该代码使用PGI编译器编译,但是当我运行此代码时,我会得到
致电custreamsynchronize返回错误700:内核执行期间的非法地址
OpenACC数据子句仅执行对象的浅副本。由于"向量"是三个指针的集合,因此这意味着将矢量放入复制子句中只会复制指示器,而不是指向的数据。
假设您正在使用PGI,最简单的事情是使用CUDA统一内存(即添加标志" -ta = tesla:Managed"),并让CUDA运行时为您管理数据运动。
否则,您需要执行向量的手动深层副本。这可能有点棘手,尤其是对向量,所以让我知道您是否需要一个例子。
再次,我强烈建议在设备上使用C 向量时使用CUDA统一内存(托管)。向量是带有三个私人指针的容器类型。给定一个OpenACC副本或更新会进行浅副本,当将向量放在数据区域中时,您将复制指针,而不是它们指向的数据。更糟糕的是,由于指针是私人的,因此无法使用设备指针进行更新。
相反,您需要创建一系列温度指针来遮蔽矢量数组的数据,然后在设备上使用此温度变量。如下:
% cat vector.data.cpp
#include <iostream>
#include <vector>
#include <cstdint>
using namespace std;
int main() {
const int bin_num = 1024;
long sum = 0;
vector<int32_t> *k1p = new vector<int32_t>[bin_num];
for (int i = 0; i < bin_num; i++) {
k1p[i].push_back(i);
}
int32_t ** temp = new int32_t*[bin_num];
int * sizes = new int[bin_num];
#pragma acc enter data create(temp[0:bin_num][0:0])
for (int i = 0; i < bin_num; i++) {
int sze = k1p[i].size();
sizes[i] = sze;
temp[i] = k1p[i].data();
#pragma acc enter data copyin(temp[i:1][:sze])
}
#pragma acc enter data copyin(sizes[:bin_num])
#pragma acc parallel loop gang vector reduction(+:sum) present(temp,sizes)
for (int i = 0; i < bin_num; i++) {
for (int j=0; j< sizes[i]; ++j) {
sum += temp[i][j];
}
}
cout << "Sum: " << sum << endl;
#pragma acc exit data delete(sizes)
#pragma acc exit data delete(temp)
delete [] sizes;
delete [] k1p;
}
% pgc++ vector.data.cpp --c++11 -ta=tesla -V18.10
% a.out
Sum: 523776
使用托管内存时,地址在统一的内存空间中,主机和设备都可以访问。因此,当您访问"开始"one_answers"结束"时,它们在设备上返回的地址有效。例如:
% cat vector.cpp
#include <iostream>
#include <vector>
#include <cstdint>
using namespace std;
int main() {
const int bin_num = 1024;
long sum = 0;
vector<int32_t>::const_iterator i2_it;
vector<int32_t> *k1p = new vector<int32_t>[bin_num];
for (int i = 0; i < bin_num; i++) {
k1p[i].push_back(i);
}
#pragma acc parallel loop reduction(+:sum) private(i2_it)
for (int i = 0; i < bin_num; i++) {
for (i2_it=k1p[i].begin(); i2_it!=k1p[i].end(); i2_it++) {
sum += *i2_it;
}
}
cout << "Sum: " << sum << endl;
}
% pgc++ vector.cpp --c++11 -ta=tesla:managed -V18.10
% a.out
Sum: 523776
另一种选择是编写您自己的向量,例如类。我写了一个基本示例,说明了使用OpenACC的平行编程第5章的一部分。可以在https://github.com/rmfarber/parallelalprogrammingwithopenacc