2015-06-09 3 views
0

У меня есть 3D-сетка трехмерных блоков, и внутри каждого блока мне нужно последовательно вычислять по слоям «z» блока. Другими словами, я хочу выполнить сначала все (x, y, 0) потоки, затем все (x, y, 1) и т. Д. Мне нужно выполнить мои потоки по слоям (подсчет слоев по оси z). Я знаю о функции __syncthreads(), но я не знаю, как синхронизировать потоки с ней так, как я хочу.Threads syncronization in CUDA

UPD:

__global__ void Kernel(//some params) 
{ 


     //some code 
     __syncthreads(); 
} 

Это позволит синхронизировать все нити в блоке. Но мне нужно выполнить все потоки, где z = 0, затем все нити, где z = 1 и т. Д.

+0

Что вы пробовали? Что не сработало? Пожалуйста, покажите нам свое решение. –

+0

Этот вопрос нуждается в более подробной информации, но я подозреваю, что ответ: определить блок потока для размера групп потоков, которые необходимо синхронизировать. Другими словами, разделите слои на отдельные блоки. – harrism

+0

@harrism, я знаю, что могу это сделать. Но в этом случае мне придется запускать ядро ​​несколько раз, и это негативно скажется на производительности. – Max

ответ

3

Вы можете использовать простой цикл и указать потоки, которые хотите выполнять на каждой итерации. Что-то вроде:

for (int z = 0; z < zmax; z++) { 
    if (threadIdx.z == z) { 
     //do whatever with x and y 
    } 
    __syncthreads(); 
} 

В каждой итерации, нити с определенным Z-индекс выполнения инструкций, а остальные простаивают; в конце каждой итерации все потоки синхронизируются.

+0

Вы уверены, что это сработает? Кажется, это может гарантировать, что все потоки с тем же z будут синхронизированы, но не могут гарантировать, что они будут вычтены в порядке возрастания z. Во-первых, потоки, где z = 0, затем z = 1 и т. Д. – Max

+0

Это не безопасное использование __syncthreads(). – harrism

+0

@harrism, насколько я вижу, речь идет не о безопасном или небезопасном использовании, это, вероятно, повлечет за собой неправильный результат. Вполне возможно, что все нити с z = 1 доходят до точки синхронизации до тех нитей, где z = 0. Следовательно, уровень 1 будет выполнен раньше слоя 0. Исправьте меня, если я ошибаюсь. – Max

1

__syncthreads() блокирует потоки внутри блока. Если вы настаиваете на использовании __syncthreads(), вам необходимо убедиться, что размер блока совпадает с размером (x * y), что необязательно возможно, и даже тогда порядок блоков не гарантируется. Альтернативным способом достижения вашей цели было бы запустить ядро ​​на каждый уровень и синхронизировать между ядрами (т. Е. Блокировать параллелизм ядра). Это, конечно, действительно зависит от того, что делает ваше точное ядро, и если разбить его так, то это возможно.

+0

Я не уверен, что вы меня поняли. Например, у меня есть один блок 2 x 2 x 2. Сначала мне нужно выделить следующие потоки: (0,0,0), (1,0,0), (0,1,0), (1,1,0). Это первый слой. Второй - (0,0,1), (1,0,1), (0,1,1), (1,1,1). Итак, для первого слоя z = 0, а для второго - z = 1. – Max

+1

@Max Да, я получил это. Первое ядро ​​обработает первый уровень (я предполагаю, что каждый слой немного больше, чем 2x2); второй слой, второй и т. д. n-й уровень обрабатывает (x, y, n). –

+0

Я думаю, что это, возможно, слишком велико, см. Мой комментарий выше о том, как использовать 2D-сетку 2D-блоков вместо запуска несколько раз. – harrism