Потоковая передача данных в ядра CUDA без многократного запуска

Я пытаюсь ускорить на GPU алгоритм, в котором я получаю асинхронный поток частиц в трехмерном пространстве $p=[x,y,t]$. Каждый вектор $p_n$ нужно умножить на набор матриц преобразования. Поскольку эти преобразования не зависят друг от друга, они могут происходить параллельно, поэтому для этого я написал ядро ​​CUDA. Это работает хорошо, но, конечно, для каждого входящего $p_n$ я запускаю ядро ​​CUDA заново. Запуск ядер CUDA влечет за собой большую потерю времени, и, таким образом, я теряю преимущество ускорения GPU. Итак, мой вопрос: могу ли я держать ядро ​​​​открытым и каким-то образом передавать ему частицы?

Если это поможет, вот мое текущее ядро:

__global__
void project(float *projection_matrix, float *vector, float *output_matrix) {
    int col_index = blockIdx.x * blockDim.x + threadIdx.x;
    int row_index = blockIdx.y * blockDim.x + threadIdx.y;
    int output_index = (col_index*3 + threadIdx.y);
    int transform_first_element = col_index * 9 + threadIdx.y * 3;
    int stride = blockDim.x*blockDim.y*gridDim.x;

    while (output_index < (NUMBER_OF_TRANSFORMS * 3)) {
        output_matrix[output_index] = projection_matrix[transform_first_element]*vector[0]+ projection_matrix[(transform_first_element+1)]*vector[1] + projection_matrix[(transform_first_element+2)]*vector[2];
        output_index += stride;
    }
}

и вот где я называю это:

...
project <<<num_blocks_dim, block_dim >>> (transformationList, inputVector, outputMatrix);
cudaDeviceSynchronize();
...

person Mr Squid    schedule 26.10.2017    source источник
comment
Да, вы можете оставить ядро ​​открытым и передавать в него частицы. Это называется парадигмой проектирования постоянных ядер, и об этом написаны статьи, а также вопросы здесь, на SO об этом.   -  person Robert Crovella    schedule 26.10.2017
comment
@RobertCrovella - Спасибо за ваш ответ, он дал мне много хороших ключевых слов, о которых я иначе не узнал бы. Я наткнулся на этот красиво изложенный пример - на самом деле написанный вами! (stackoverflow.com/questions/33150040/). Вы бы порекомендовали такой дизайн производитель/потребитель для моего варианта использования? Можно ли сделать это сейчас иначе, чем в 2015 году?   -  person Mr Squid    schedule 27.10.2017
comment
Я не вижу достаточного описания вашего варианта использования, чтобы дать рекомендацию. В основном я отвечал на вопрос, могу ли я держать ядро ​​​​открытым и каким-то образом направлять в него частицы? Изменение, которое я бы сделал сегодня по сравнению с 2015 годом, заключалось бы в использовании совместных групп — новой функции в CUDA 9 — для управления постоянным дизайном ядра.   -  person Robert Crovella    schedule 27.10.2017


Ответы (1)


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

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

Если они исходят от ЦП, а затем возвращаются к ЦП, я был бы удивлен, если бы вы вообще могли заставить его окупиться, если только количество матриц не является довольно большим. (По сравнению с хорошо оптимизированным кодом процессора SIMD.)

person Zalman Stern    schedule 26.10.2017
comment
@ZalmanStein Я не рассматривал SIMD как альтернативу. Я, конечно, не хотел бы начинать изучать SSE, так как мне это кажется очень сложным, но я мог бы достичь того, чего хочу, с библиотекой более высокого уровня, такой как Intel MKL, как вы думаете? Как правило, в каких случаях следует использовать CPU SIMD вместо ускорения GPU? - person Mr Squid; 27.10.2017
comment
Основная проблема заключается в стоимости потока данных. Передача небольшого фрагмента данных в/из графического процессора связана с фиксированными накладными расходами, и потребуется много вычислений, чтобы сделать это целесообразным. Проверьте Halide, halide-lang.org. Это может позволить писать код таким образом, который позволяет эффективно нацеливать ЦП и ГП. (Конечно, немного зависит от специфики. Сразу хочу сказать, что я работаю над Halide.) - person Zalman Stern; 27.10.2017