CUDA cudaMemcpyToSymbol () выдает ошибку «неверный аргумент» - PullRequest
5 голосов
/ 13 марта 2012

Проблема

Я пытаюсь скопировать массив int в постоянную память устройства, но постоянно получаю следующую ошибку:

[ОШИБКА] «неверный аргумент» (11) в «main.cu» в строке «386»

Код

Разработано много кода, поэтому я собираюсь упростить то, что имею.

Я объявил переменную устройства __constant__ в верхней части моего файла main.cu вне функции.

__device__ __constant__ int* dic;

У меня также есть переменная хоста, flatDic, которая malloc'ed следующим образом, внутри main():

int* flatDic = (int *)malloc(num_codewords*(bSizeY*bSizeX)*sizeof(int));

Затем я пытаюсь скопировать содержимое flatDic в dic, также в main():

cudaMemcpyToSymbol(dic, flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int));

Этот cudaMemcpyToSymbol() вызывает это строку 386 main.cu, и именно здесь выдается вышеупомянутая ошибка.

Что я пробовал

Вот что я пытался решить до сих пор:

Я пробовал все следующее, возвращая всегда одну и ту же ошибку:

cudaMemcpyToSymbol(dic, &flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int));

cudaMemcpyToSymbol(dic, flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int));

cudaMemcpyToSymbol(dic, &flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int), 0, cudaMemcpyHostToDevice);

cudaMemcpyToSymbol(dic, flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int), 0, cudaMemcpyHostToDevice);

Я также пытался cudaMalloc() переменную dic перед вызовом cudaMemcpyToSymbol(). В cudaMalloc() не выдается никаких ошибок, но cudaMemcpyToSymbol() ошибка сохраняется.

cudaMalloc((void **) &dic, num_codewords*(bSizeY*bSizeX)*sizeof(int));

Я также тщательно обыскиваю в Интернете, документации, форумах, примерах и т. Д. Все безрезультатно.

Кто-нибудь видит что-то не так с моим кодом? Заранее спасибо.

1 Ответ

4 голосов
/ 13 марта 2012

cudaMemcpyToSymbol копирует в постоянную переменную, здесь вы пытаетесь скопировать несколько байтов типа int (выделенный массив) в указатель типа int *.Эти типы не являются одинаковыми, следовательно, invalid type.Чтобы это работало, вам нужно скопировать массив (int) (выделенный) на устройство (статическая длина), массив (int (постоянный)), например:

__device__ __constant__ int dic[LEN];

Пример из Руководство по программированию в CUDA C (которое я предлагаю вам прочитать - это неплохо!):

__constant__ float constData[256];
float data[256];
cudaMemcpyToSymbol(constData, data, sizeof(data));
cudaMemcpyFromSymbol(data, constData, sizeof(data));

Насколько мне известно, вы также можете cudaMemcpyToSymbol указатель на указатель (в отличие от вашего примерагде вы копируете массив в указатель), но помните только, что указатель будет постоянным, а не память, на которую он указывает на вашем устройстве.Если вы собираетесь пойти по этому пути, вам нужно будет добавить cudaMalloc, а затем cudaMemcpyToSymbol полученный ptr в память устройства на ваше устройство __constant__ var.ОПЯТЬ, в этом случае значения массива НЕ БУДУТ постоянными - ТОЛЬКО указатель на память будет.

Ваш вызов для этого случая будет выглядеть примерно так:

int * d_dic;
cudaMalloc((void **) &d_dic, num_codewords*(bSizeY*bSizeX)*sizeof(int));
cudaMemcpyToSymbol(c_dic_ptr, &d_Dic, sizeof(int *));

Также выследует обернуть ваши вызовы CUDA во время отладки внутри логики проверки ошибок.Я заимствовал следующую логику из talonmies :

__inline __host__ void gpuAssert(cudaError_t code, char *file, int line, 
                 bool abort=true)
{
   if (code != cudaSuccess) 
   {
      fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code),
          file, line);
      if (abort) exit(code);
   }
}

#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }

Для вызова просто оберните в него свой вызов CUDA следующим образом:

gpuErrchk(cudaMemcpyToSymbol(dic, flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int)));

Программирование завершитсяс сообщением об ошибке, если у вас возникли проблемы с выделением ресурсов или другие распространенные ошибки.

Чтобы проверить ядро, выполните что-то вроде:

MyKernel<<<BLK,THRD>>>(vars...);

//Make sure nothing went wrong.
gpuErrchk(cudaPeekAtLastError());
gpuErrchk(cudaDeviceSynchronize());

Благодаря talonmies длякод проверки ошибок!

Примечание: Даже если вы выполняете ванильное cudaMemcpy, ваш код потерпит неудачу, так как вы не cudaMalloc отредактировали память для своего массива - в этом случае, однако, сбой, скорее всего, будет эквивалентен ошибке в графическом процессоре (вероятно, *)1047 *), поскольку указатель будет содержать какое-то нежелательное значение, и вы будете пытаться записать в память адрес, заданный этим нежелательным значением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...