Я пытаюсь установить постоянные значения в постоянной памяти графического процессора перед запуском ядра, которому нужны эти значения.

Мой код (упрощенно):

__constant__ size_t con_N;

int main() 
{

    size_t N;
    size_t* dev_N = NULL;
    cudaError_t cudaStatus;

    //[...]

    cudaStatus = cudaGetSymbolAddress((void **)&dev_N, &con_N);
    if (cudaStatus != cudaSuccess) {
        cout<<"cudaGetSymbolAddress (dev_N) failed: "<<cudaGetErrorString(cudaStatus)<<endl;
    }

Я планировал потом cudaMemcpy отправить N на dev_N.

Однако все, что я получил на этом этапе кода, это:

cudaGetSymbolAddress (dev_N) failed: invalid device symbol

Я работаю с CUDA 6.5, поэтому это не проблема с цитируемыми символами, как в большинстве вопросов и ответов, которые я проверял до сих пор.

Я попытался заменить con_N на con_N[1] (и удалить & перед con_N в параметрах cudaGetSymbolAddress): результат тот же.

Поскольку прототипом этой функции является cudaGetSymbolAddress(void **devPtr , const void* symbol ), я предположил, что он хочет получить адрес моего символа. Однако я попытался использовать cudaStatus = cudaGetSymbolAddress((void **)&dev_N, (const void*) con_N); и получил то же сообщение.

Я также получаю такое же сообщение об ошибке, когда удаляю cudaGetSymbolAddress((void **)&dev_N, &con_N) и вместо этого использую cudaMemcpyToSymbol(&con_N, &N, sizeof(size_t)).

Боюсь, что упустил что-то важное. Любая помощь будет оценена.

2
eyam 4 Ноя 2014 в 16:01

2 ответа

Лучший ответ

Правильное использование cudaGetSymbolAddress:

cudaGetSymbolAddress((void **)&dev_N, con_N)

Я показываю это на простом примере ниже.

Как поясняется в документации, символ должен физически находиться на устройстве. Соответственно, использование &con_N в вызове API кажется бессмысленным, поскольку, будучи cudaGetSymbolAddress API хоста, доступ к адресу чего-либо, находящегося на устройстве, напрямую с хоста невозможен. Я не уверен, что прототип, представленный в документе CUDA Runtime API, лучше читать как `

template<class T>
cudaError_t cudaGetSymbolAddress (void **devPtr, const T symbol)

С ссылкой на символ устройства вместо адреса символа устройства .

#include <stdio.h>

__constant__ int const_symbol;

/********************/
/* CUDA ERROR CHECK */
/********************/
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t code, const 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);
   }
}

/***************/
/* TEST KERNEL */
/***************/
__global__ void kernel() {

    printf("Address of symbol from device = %p\n", &const_symbol);

}

/********/
/* MAIN */
/********/
int main() 
{
    const int N = 16;
    int *pointer = NULL;

    gpuErrchk(cudaGetSymbolAddress((void**)&pointer, const_symbol));

    kernel<<<1,1>>>();

    printf("Address of symbol from host = %p\n", pointer);

    return 0;
}
4
Vitality 5 Ноя 2014 в 00:20
Спасибо, это имеет смысл. Должен добавить, что мне не удалось скомпилировать cudaGetSymbolAddress((void **)&dev_N, con_N) , но только потому, что весь код, о котором я говорю, был в файле .cpp, а не в файле .cu. Обертывание моих вызовов решило мои проблемы с компиляцией (благодаря этой теме: stackoverflow.com/questions/20535683/… )
 – 
eyam
5 Ноя 2014 в 14:14

На мой взгляд, строка вашего кода должна быть исправлена, как показано ниже.

cudaStatus = cudaGetSymbolAddress((void **)&dev_N, con_N);

Надеюсь, это тебе поможет.

1
Wang Wang 4 Ноя 2014 в 16:55
Спасибо за ответ! Прототипом этой функции является cudaGetSymbolAddress(void * * devPtr, const void* symbol), поэтому я подумал, что она хочет получить адрес моего символа. Однако я попробовал это (мне пришлось использовать con_N как const void*), и я все еще застрял с тем же сообщением об ошибке.
 – 
eyam
4 Ноя 2014 в 17:13
Вы не должны приводить con_N как const void*. это причина ошибки. кроме того, вам не нужно следовать прототипу для функций, работающих с такими символами, как cudaGetSymbolAddress, cudaMemcpyToSymbol, потому что они могут отличаться в зависимости от среды cuda.
 – 
Wang Wang
4 Ноя 2014 в 17:26
@Wang_Wang: Хорошо, спасибо за этот совет. Однако моя IDE не компилируется без этого приведения... (иначе я был бы рад обойтись без него)
 – 
eyam
4 Ноя 2014 в 17:36
@eyam, первым, кто дал тебе ответ, был я. Кстати, почему вы не номинировали меня?
 – 
Wang Wang
5 Ноя 2014 в 18:11
@Wang_Wang, ответ Джека дал больше деталей и объяснений, поэтому я подумал, что он более актуален для людей, ищущих ответы. Однако я благодарен за ваш ответ (будьте уверены, что я тоже проголосовал бы за него, если бы у меня было достаточно репутации, чтобы сделать это)
 – 
eyam
5 Ноя 2014 в 18:35