Как обменять двухмерный элемент между центральным процессором и графическим процессором?
Я пытался использовать этот 2d элемент как w [0: (n_hidden * i) -1], но обратная связь с компилятором говорит мне, что что-то не так
Это функция алгоритма RBM:
double RBM::propdown(int *h, int i, double b) {
#pragma acc data region \
copyin(w[0:(n_hidden*i)-1],h[0:n_hidden],b) create(pre_sigmoid_activation)
double pre_sigmoid_activation = 0.0;
#pragma acc parallel loop reduction(+:pre_sigmoid_activation)
for(int j=0; j<n_hidden; j++) {
pre_sigmoid_activation += W[j][i] * h[j];
}
pre_sigmoid_activation += b;
return sigmoid(pre_sigmoid_activation);
#pragma acc exit data \
delete ( pre_sigmoid_activation)
}
Не нужно линеаризовать массив. Просто используйте несколько скобок.
#pragma acc data copyin(W[0:n_hidden][0:N])
Я вижу и ряд других вопросов.
В директиве data нет предложения «region». Вы можете путать это с предложением «ввод данных» или моделью PGI Accelerator, которая была основой для OpenACC.
Нет необходимости помещать «b» в предложение data, поскольку оно фактически не используется в области вычислений. Кроме того, помещая его в предложение data, вы делаете «b» глобальной ссылкой на устройство. Лучше оставить скаляры, доступные только для чтения, из предложений данных, чтобы значение передавалось в качестве аргумента, а не для его получения из глобальной памяти.
Опять же, поместив скалярную переменную «pre_sigmoid_activation» в предложение данных, вы создали глобальную переменную. Здесь результат сокращения будет сохранен в этой переменной устройства и не будет автоматически обновляться на хосте. Для этого вам нужно добавить директиву «update». Еще лучше, просто удалите его из предложения данных, и результат сокращения будет обновлен до переменной хоста.
У вас есть непревзойденная директива «выходных данных» (должна быть соответствующая директива «вводить данные»). Кроме того, директива помещается после оператора return, поэтому никогда не будет выполняться, оставляя данные на устройстве.
Наконец, поскольку C ++ чувствителен к регистру, убедитесь, что имена переменных в директивах OpenACC соответствуют фактическим именам переменных. т.е. «W» вместо «w».
Вот как я бы написал цикл. Обратите внимание, что я не знаю размер второго измерения «W», поэтому просто использовал «N». Пожалуйста, обновите соответственно.
#pragma acc data copyin(W[0:n_hidden][0:N],h[0:n_hidden])
{
#pragma acc parallel loop reduction(+:pre_sigmoid_activation)
for(int j=0; j<n_hidden; j++) {
pre_sigmoid_activation += W[j][i] * h[j];
}
}
Других решений пока нет …