CUDA пишет в глобальную память, не видимую другими перекосами - PullRequest
0 голосов
/ 29 октября 2018

Я пытался объяснить глобальную память тому, кто плохо знаком с CUDA. Я придумал следующее фиктивное ядро, которое блокирует другие потоки в других деформациях, пока выбранный деформация не установит глобальную переменную в другое значение:

__global__ void with_sync()
{
    while (threadIdx.x / 32 != 0)
    {
        if (is_done != 0)
        {
            break;
        }
    }

    if (threadIdx.x / 32 == 0)
    {
        is_done = 1;
        printf("I'm done!\n");
    }
}

Переменная is_done объявлена ​​вне функции как __device__ __managed__ int (что, исправьте меня, если я ошибаюсь, означает, что переменная будет находиться в глобальном пространстве памяти.

Однако, когда я запускаю это ядро ​​(1024 1D потоков в одном блоке), примерно так:

with_sync<<<1, 1024>>>();
cudaDeviceSynchronize();

I'm done распечатывается как ожидалось. Однако программа CUDA не завершает свою работу (я поместил cudaDeviceSynchronize() в коде хоста, чтобы он ожидал всех потоков). Это заставляет меня задуматься, не получили ли другие деформации изменения в переменную is_done. Однако я понимаю, что глобальная память подразумевает, что значение можно увидеть на уровне устройства (то есть, по крайней мере, все блоки в сетке).

У меня следующий вопрос: существует ли какое-либо кэширование / оптимизация, выполненная CUDA, которая делает его таким, чтобы могло возникнуть это несовместимое представление глобальной памяти? Есть ли способ получить доступ к «последнему» значению из переменной, которая находится в глобальной памяти?

1 Ответ

0 голосов
/ 29 октября 2018

Есть ли какое-либо кэширование / оптимизация, выполненная CUDA, которая делает его таким, чтобы могло возникнуть это несовместимое представление глобальной памяти? Есть ли способ получить доступ к «последнему» значению из переменной, которая находится в глобальной памяти?

Да, есть поведение кеширования. Вы можете изменить его с помощью квалификатора volatile .

Вот рабочий пример:

$ cat t310.cu
#include <stdio.h>

#ifndef USE_VOLATILE
__device__ __managed__ int is_done = 0;
#else
__device__ volatile __managed__ int is_done = 0;
#endif

__global__ void with_sync()
{
    while (threadIdx.x / 32 != 0)
    {
        if (is_done != 0)
        {
            break;
        }
    }

    if (threadIdx.x / 32 == 0)
    {
        is_done = 1;
        printf("I'm done!\n");
    }
}



int main(){

  with_sync<<<1,1024>>>();
  cudaDeviceSynchronize();
}
$ nvcc -o t310 t310.cu
$ ./t310
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
^C
$ nvcc -o t310 t310.cu -DUSE_VOLATILE
$ ./t310
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
$

(Если неясно, что первый запуск выше был прерван Ctrl-C из-за зависания)

Tesla P100 PCIE CUDA 10.0, CentOS 7

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