Я аспирант по биофизике, пытаюсь запрограммировать модель агрегации белков с использованием PyCUDA и Scipy's ODEInt
. За последние две недели я запустил код, но он очень медленный. Посмотрим, смогу ли я объяснить, что делает мой код.
У меня есть np
массив N
концентраций, где каждый элемент представляет собой концентрацию полимера длиной i+1
. У меня есть функция, которая вычисляет скорость изменения концентраций полимера с использованием CUDA
, где каждое ядро вычисляет скорость изменения одного полимера определенной длины. Во время этого вычисления поток должен суммировать массив длины (N-i-1)
, что резко замедляет мой код.
Немного почитав и погуглив, я наткнулся на параллельное сокращение как способ вызвать параллелизм, чтобы последовательные вычисления, такие как сумма массива, выполнялись намного быстрее. Конечно, я имею в виду слайды PowerPoint от Марка Харриса. Это было отличное чтение, и это похоже на потенциальный способ резко ускорить мой код, но у меня есть несколько вопросов:
Если количество полимеров N должно составлять ~ 8700-9000, возможно ли использовать CUDA для одновременного сокращения этих N массивов? Выполняя быстрые вычисления (опять же, благодаря отличному объяснению SO о том, как рассчитать максимальное количество одновременных потоков), я получаю для своего GTX Titan, что у меня может быть 15 * 64 * 32 = 30720 потоков одновременно. Если я вызываю свое ядро на ~ 8960 ядрах за раз, у меня останется только 21760 потоков, верно? Поскольку кажется, что вам нужно как минимум (длина массива / 2) потоков, чтобы правильно его уменьшить, то я обречен.
Я думал, что, возможно, я мог бы использовать оставшиеся потоки, разделив их и уменьшив несколько больших массивов за раз последовательно.
Не знаю ... Я просто аспирант по физике. Я думал, что спрошу у профессионалов, прежде чем отправиться в долгое путешествие в неверном направлении. Можно ли легко и эффективно сказать ядру, что нужно что-то уменьшить?
Спасибо, Карстен
Вот представление того, что я пытаюсь сделать.
fluxes and concs are np.arrays
dcdt(concs, t)
Call CUDA to calculate fluxes
Thread
0 fluxes[i] = stuff + sum(concs[n] for n from 1 to 9000)
1 fluxes[i] = stuff + sum(concs[n] for n from 2 to 9000)
2 fluxes[i] = stuff + sum(concs[n] for n from 3 to 9000)
...
N fluxes[i] = stuff
Вы заметите, что сумма массивов, о которых мы говорили, в основном представляет собой уменьшенную версию того же массива для каждого из потоков. Это заставляет меня задуматься, стоит ли мне просто делать это на хосте.