Cuda Как запустить много потоков из глобальной функции?Одно ядро, которое запускает много потоков - PullRequest
0 голосов
/ 21 ноября 2011

Мне нужно сделать одну часть вычислений параллельной.Это вычисления по вектору, и иногда мне нужно делать одну операцию для каждого значения.Поэтому я хочу, чтобы это было параллельно.

Я не могу объяснить свои расчеты на примере (это единственный простой пример, а не мой алгоритм): я перемещаю указатель вперед, и когда я нашел число 5, то я добавляю 5к каждому числу в векторе.

Поэтому я хочу не делать этого на хосте и копировать весь большой вектор на хост <=> устройства (повторяемый) после каждого перемещения указателя.Я полагаю, что это может быть менее эффективно, чем делать все на хосте.

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

Вотпросто справиться, представив мою проблему:

__device__ void devFunction(long long unsigned int *arr, long long unsigned int param, long long unsigned int N) {
    long long unsigned int i = blockIdx.x* blockDim.x+ threadIdx.x;
    // do something ...
}

__global__ void globFunction(long long unsigned int *arr, long long unsigned int N) {

    do {
        devFunction(arr, param, N); // I want to run many threads here like <<<...>>>

        // do something ...

    } while(/* ... */);
}


int main() {
    // declare array, alloc memory, copy memory, etc.
    globFunction<<< 400000, 256>>>(arr, N); // I think here should be <<<1,1>>>
    // do something ...
    return 0;
}

Так можно это сделать?Запускать несколько функций параллельно из ядра?Любые другие решения?

1 Ответ

5 голосов
/ 21 ноября 2011

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

В качестве грубого примера скелета код должен выглядеть примерно так:

__global__ void kernel(int * indata, int * outdata)
{
  unsigned int tid = threadId.x + blockDim.x * blockId.x; // or suitable analogue

  device_computation(indata + tid, outdata + tid);
}

__device__ void device computation(int * in, int * out)
{
  // This code does not care about the thead ID
  // -- it is already local to one single thread
  *out = *in * 2;
}

Вы действительно не должны этого делать любой должен знать indata[j], чтобы вычислить indata[i].Если вы это сделаете, то вам придется разделить ваши данные таким образом, чтобы все данные, необходимые для выполнения вычислений, были видны исключительно одному потоку.

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

(Пример слишком упрощен; возможность использования памяти с общим блоком, безусловно, должна быть принята во внимание.не влияет на то, что каждый поток должен иметь возможность работать независимо от других потоков.)

...