Использование разных потоков для ядер CUDA делает возможным одновременное выполнение ядра. Поэтому ядра n
на n
потоках теоретически могут выполняться одновременно, если они подходят к оборудованию, верно?Совместное выполнение ядра CUDA с несколькими ядрами на поток
Теперь я столкнулся со следующей проблемой: Не существует 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. Я измерил время, необходимое для полного решения вычислений, т.е. е. GPU должен вычислить все ядра n * m
. Предполагается следующее: при полностью параллельном выполнении ядра время выполнения примерно (желательно) 1/n
времени, необходимого для выполнения всех ядер в порядке, в результате чего должно быть возможно одновременное выполнение двух или более ядер. Я обеспечиваю это, используя только два разных потока прямо сейчас.
Я могу измерить четкую разницу в отношении времени выполнения между использованием потоков, как описано, и перемещением ядер чередующихся, i. е .:
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, см. Комментарии ниже).
Edit # 3: Оборудование является NVIDIA Tesla M2090 (т.е. Ферми, вычислить способность 2,0)
Возможно, вам понадобится использовать некоторые примитивы синхронизации потока для обеспечения требуемого порядка выполнения. Но не могли бы вы немного рассказать о том, как вы сделали свои измерения в своем вопросе, и не могли бы вы также подтвердить, что когда вы пишете «Stream 0», вы буквально не понимаете поток CUDA 0? – talonmies
Я уточнил измерение (по крайней мере, надеюсь на это). С потоками я имею в виду примеры 'cudaStream_t', как описано в [CUDA C Programming Guide] (http://developer.download.nvidia.com/compute/DevZone/docs/html/C/doc/CUDA_C_Programming_Guide.pdf), раздел 3.2.5 (асинхронное параллельное выполнение). –
Возможно, вы неправильно поняли то, что я просил - я имею в виду один из потоков потока CUDA потока 0, потому что поток 0 (поток по умолчанию) является синхронным. – talonmies