CUDA: вызов функции __device__ из ядра

#cuda

#cuda

Вопрос:

У меня есть ядро, которое вызывает функцию устройства внутри инструкции if. Код выглядит следующим образом:

 __device__ void SetValues(int *ptr,int id)
{
    if(ptr[threadIdx.x]==id) //question related to here
          ptr[threadIdx.x]  ;
}

__global__ void Kernel(int *ptr)
{
    if(threadIdx.x<2)
         SetValues(ptr,threadIdx.x);
}
  

В потоках ядра 0-1 одновременно вызываются setValues. Что происходит после этого? Я имею в виду, что теперь есть 2 одновременных вызова setValues. Выполняется ли каждый вызов функции последовательно? То есть они ведут себя как два вызова функций ядра?

Ответ №1:

CUDA фактически внедряет все функции по умолчанию (хотя Fermi и более новые архитектуры также поддерживают надлежащий ABI с указателями на функции и реальными вызовами функций). Итак, ваш пример кода компилируется примерно так

 __global__ void Kernel(int *ptr)
{
    if(threadIdx.x<2)
        if(ptr[threadIdx.x]==threadIdx.x)
            ptr[threadIdx.x]  ;
}
  

Выполнение происходит параллельно, точно так же, как обычный код. Если вы встроите в функцию скачок памяти, нет механизма сериализации, который может вас спасти.

Комментарии:

1. у меня есть плата fermi. означает ли это, что функция не является встроенной? следовательно, threadIdx.x в setValues — это все потоки, а не только потоки 0 и 1?

2. Функции по-прежнему встроены по умолчанию в Fermi. Я думаю, я понимаю, о чем вы на самом деле спрашиваете сейчас — о том, какова область действия встроенных переменных для каждого потока (например, threadIdx) внутри функций устройства . Мне становится теплее?

3. да, это мой вопрос. но поскольку функции устройства являются встроенными.. тогда я предполагаю, что область действия потоков такая же, как и при вызове с использованием <<<блоки, потоки>>> но из-за ветвления только потоки 0 и 1 выполняют ptr[threadIdx.x] . это правильно?