Обновление: Следующие результаты для рукописного FFT алгоритма GPU на 2005 аппаратных средств (Nvidia 7800 GTX), но показывает принцип CPU-GPU Tranfer узкие
Накладные не вызов, но компиляция программы GPU и передача данных между GPU и хостом. ЦП очень оптимизирован для функций, которые могут выполняться полностью в кеше, а латентность памяти DDR3 намного ниже, чем шина PCI-Express, обслуживающая GPU. Я сам это испытал при написании подпрограмм GPU FFT (до CUDA). См. this related question.
N FFTw (s) GPUFFT (s) GPUFFT MFLOPS GPUFFT Speedup
8 0 0.00006 3.352705 0.006881
16 0.000001 0.000065 7.882117 0.010217
32 0.000001 0.000075 17.10887 0.014695
64 0.000002 0.000085 36.080118 0.026744
128 0.000004 0.000093 76.724324 0.040122
256 0.000007 0.000107 153.739856 0.066754
512 0.000015 0.000115 320.200892 0.134614
1024 0.000034 0.000125 657.735381 0.270512
2048 0.000076 0.000156 1155.151507 0.484331
4096 0.000173 0.000215 1834.212989 0.804558
8192 0.000483 0.00032 2664.042421 1.510011
16384 0.001363 0.000605 3035.4551 2.255411
32768 0.003168 0.00114 3450.455808 2.780041
65536 0.008694 0.002464 3404.628083 3.528726
131072 0.015363 0.005027 3545.850483 3.05604
262144 0.033223 0.012513 3016.885246 2.655183
524288 0.072918 0.025879 3079.443664 2.817667
1048576 0.173043 0.076537 2192.056517 2.260904
2097152 0.331553 0.157427 2238.01491 2.106081
4194304 0.801544 0.430518 1715.573229 1.861814
В приведенной выше таблице показаны тайминги реализации FFT GPU и реализации ЦП на основе размера ядра. Для меньших размеров передача данных в/из графического процессора доминирует. Меньшие ядра могут выполняться на ЦПУ, некоторые реализации/размеры полностью в кеше. Это делает CPU лучшим выбором для небольших операций.
Если, с другой стороны, вам необходимо выполнить большие партии работы с данными с минимальными перемещениями на/из графического процессора, тогда GPU будет бить CPU вниз.
Что касается измерения эффекта в вашем примере, я бы предложил выполнить такой эксперимент, как выше. Попробуйте выработать FLOPS, рассчитанные для каждого размера матрицы, и выполнить тест на CPU и GPU для разных размеров матрицы. Выведите в CSV-файл размер, время и FLOPS для GPU и CPU. Для любого профилирования убедитесь, что вы запускаете несколько сот итераций своего кода и времени, а затем разделите общее время на итерации, чтобы получить время цикла. Попробуйте различные формы матрицы также, если ваш алгоритм позволяет (например, 10x100, а не 100x10).
Используя эти данные, вы можете почувствовать, что такое накладные расходы. Чтобы точно определить тот же эксперимент, но замените внутренний шейдерный код, выполняемый на графическом процессоре, без операции (просто скопируйте с ввода на вывод).
Надеется, что это помогает,
Чтобы вы могли динамически выбирать, отправлять ли задание в CUDA или просто ради интереса? – Rup
@Rup: Просто интересно узнать, что на самом деле стоит звонок. и определить, является ли медленный код моей ошибкой или просто продуктом архитектуры ;-) –
Для небольших объемов данных не только накладные расходы на вас, но и на отсутствие возможного параллелизма. Графический процессор зависит от наличия достаточного количества потоков, чтобы скрыть задержки (что намного хуже на gpu, а затем на CPU). Даже без накладных расходов на вызовы графический процессор, вероятно, будет медленнее, чем процессор, если работа не будет разбита на ** lots ** потоков. Лоты могут легко означать тысячи потоков. – Grizzly