Опять же, я настоятельно рекомендую использовать унифицированную память CUDA (управляемую) при использовании векторов C ++ на устройстве.Векторы представляют собой контейнерный тип с тремя частными указателями.Если копия или обновление 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
При использовании управляемой памяти адреса находятся в едином пространстве памяти, доступном как для хоста, так и для устройства.Следовательно, когда вы открываете «начало» и «конец», адреса, которые они возвращают на устройстве, действительны.Например:
% 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
Другой вариант - написать свой собственный вектор, подобный классу.Я написал основной пример того, как это сделать, как часть главы 5 Параллельное программирование с OpenACC .Образцы кода можно найти по адресу https://github.com/rmfarber/ParallelProgrammingWithOpenACC