Использование разных потоков для ядер CUDA делает возможным параллельное выполнение ядра.Следовательно, n
ядра в n
потоках теоретически могут работать одновременно, если они вписываются в аппаратное обеспечение, верно?
Теперь я сталкиваюсь со следующей проблемой: нет n
отдельных ядер, но n*m
где m
ядра должны быть выполнены по порядку.Например, n=2
и m=3
приведут к следующей схеме выполнения с потоками:
Stream 1: <<<Kernel 0.1>>> <<<Kernel 1.1>>> <<<Kernel 2.1>>>
Stream 2: <<<Kernel 0.2>>> <<<Kernel 1.2>>> <<<Kernel 2.2>>>
Мое наивное предположение состоит в том, что ядра x.0 и y.1 должны выполняться одновременно (с теоретической точки зрения).зрения) или, по крайней мере, не последовательно (с практической точки зрения).Но мои измерения показывают, что это не так, и кажется, что выполняется последовательное выполнение (то есть K0.0, K1.0, K2.0, K0.1, K1.1, K2.1).Ядра сами по себе очень малы, поэтому параллельное выполнение не должно быть проблемой.
Теперь мой подход заключается в том, чтобы выполнить своего рода диспетчеризацию, чтобы убедиться, что ядра поставлены в очередь с чередованием в планировщикна ГПУ.Но когда имеешь дело с большим количеством потоков / ядер, это может принести больше вреда, чем пользы.
Хорошо, прямо к сути: какой подход (или, по крайней мере, другой) подход к решению этой ситуации?
Редактировать: Измерения выполняются с использованием событий CUDA.Я измерил время, необходимое для полного решения вычислений, т.е. графический процессор должен вычислять все ядра n * m
.Предположение таково: при полностью параллельном выполнении ядра время выполнения примерно (в идеале) 1/n
времени, необходимого для выполнения всех ядер по порядку, при этом должно быть возможно, что два или более ядра могут выполняться одновременно.Я гарантирую это, используя только два отдельных потока прямо сейчас.
Я могу измерить явную разницу во времени выполнения между использованием потоков, как описано, и диспетчеризацией чередующихся ядер, то есть:
Loop: i = 0 to m
EnqueueKernel(Kernel i.1, Stream 1)
EnqueueKernel(Kernel i.2, Stream 2)
против
Loop: i = 1 to n
Loop: j = 0 to m
EnqueueKernel(Kernel j.i, Stream i)
Последнее приводит к увеличению времени выполнения.
Правка # 2: Изменены номера потоков, чтобы они начинались с 1 (вместо 0, см. комментарииниже).
Редактировать # 3: Аппаратное обеспечение - NVIDIA Tesla M2090 (т. е. Fermi, вычислительная мощность 2.0)