Cuda Memory разделяется на все темы - PullRequest
1 голос
/ 17 ноября 2011

Я начал свое приключение с CUDA сегодня. Я пытаюсь поделиться неподписанным int среди всех потоков. Все темы изменяют это значение. Я скопировал это одно значение на устройство с помощью cudaMemcpy. Но в конце, когда вычисления завершены, я получил, что это значение равно 0.

Может быть, несколько потоков пишут в эту переменную одновременно? Я не уверен, должен ли я использовать какие-либо семафоры или блокировать эту переменную, когда поток начинает писать или что.

EDIT:

Трудно сказать более подробно, потому что мой вопрос в общем, как его решить. На самом деле я не пишу никаких алгоритмов, только тестирую CUDA.

Но если вы хотите ... Я создал вектор, который содержит несколько значений (без знака int). Я попытался сделать что-то вроде поиска значений, превышающих заданное общее значение, но когда значение из вектора больше, я добавляю 1 к элементам вектора и сохраняю общее значение.

Это выглядит так:

__global__ void method(unsigned int *a, unsigned int *b, long long unsigned N) {
    int idx = blockIdx.x* blockDim.x+ threadIdx.x;
    if (a[idx]>*b && idx < N) 
        *b = a[idx]+1;
}

Как я уже сказал, это бесполезный код, только для тестирования, но мне интересно, как это сделать ...

Ответы [ 3 ]

1 голос
/ 17 ноября 2011

Если значение находится в разделяемой памяти, оно будет локальным только для каждого потока, работающего в одном мультипроцессоре (то есть для каждого потока), а НЕ для каждого потока, работающего для этого ядра.Вам определенно нужно будет выполнить атомарные операции (такие как atomicAdd и т. Д.), Если вы ожидаете, что каждый поток будет записывать в переменную simultanesouly.Имейте в виду, что это будет сериализовать все одновременные запросы потоков для записи в переменную.

1 голос
/ 17 ноября 2011

"Мой вопрос в общем, как использовать глобальную разделяемую память для всех потоков."

Для чтения вам не нужно ничего особенного.То, что вы сделали, работает быстрее на устройствах Fermi, потому что они имеют кеш, медленнее на других.

Если вы читаете значение после того, как другие потоки изменили его, у вас нет возможности ждать, пока все потоки завершат свои операцииперед чтением значения, которое вы хотите, чтобы оно могло не соответствовать ожидаемому.Единственный способ синхронизировать значение в глобальной памяти между всеми запущенными потоками - это использовать разные ядра.После изменения значения, которое вы хотите разделить между всеми потоками, ядро ​​завершает работу, и вы запускаете новый, который будет работать с общим значением.

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

Чтобы узнать о доступных элементарных функциях, прочитайте раздел B.11 Руководства по программированию CUDA C доступный здесь .

То, что вы спросили, будет:

__global__ void method(unsigned int *a, unsigned int *b, long long unsigned N) {
    int idx = blockIdx.x* blockDim.x+ threadIdx.x;
    if (a[idx]>*b && idx < N) 
        //*b = a[idx]+1;
        atomicAdd(b, a[idx]+1);
}
0 голосов
/ 17 ноября 2011

edit - удаленная ошибка

Хотя в идеале вы не хотите этого делать - если только вы не уверены, что все потоки займут примерно одно и то же время.

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