Ваша задача, очевидно, связана с памятью, но это не значит, что вы не можете получить прибыль от графического процессора, однако она, вероятно, менее прямолинейна, чем для задачи, связанной с процессором.
Давайте посмотрим на общую конфигурацию и немного посчитаем:
- Пропускная способность памяти CPU-RAM составляет ок. 24 ГБ / с
- пропускная способность CPU-GPU составляет ок. 8GB / s
- Пропускная способность памяти GPU-RAM составляет ок. 180GB / с
Давайте предположим, что нам нужно передать 24 ГБ данных для выполнения задачи, поэтому у нас будет следующее оптимальное время (вопрос о том, как и как достичь этого времени - другой вопрос!):
- сценарий: только время процессора = 24 ГБ / 24 ГБ / с = 1 секунда.
- : данные должны передаваться из ЦП в графический процессор (24 ГБ / 8 ГБ / с = 3 секунды) и обрабатываться там (24 ГБ / 180 ГБ / с = 0,13 секунды), что приводит к 3,1 секунды.
- : данные уже находятся на устройстве, поэтому требуется только 24 ГБ / 180 ГБ / с = 0,13 секунды.
Как видно, существует потенциал для ускорения, но только в 3. сценарии - когда ваши данные уже находятся на GPU-устройстве.
Однако достижение максимальной пропускной способности является довольно сложной задачей.
Например, при обработке матрицы по строкам на ЦП вы хотели бы, чтобы ваши данные были в главном порядке строк (C-порядке), чтобы получить максимальную отдачу от L1-кэша: while читая двойное число, вы фактически загружаете 8 двойных в кеш, и вы не хотите, чтобы они были удалены из кеша, прежде чем вы сможете обработать оставшиеся 7.
В GPU, с другой стороны, вы хотите, чтобы обращения к памяти были объединенными , например. поток 0
должен иметь доступ к адресу 0
, поток 1
- адрес 1
и так далее. Чтобы это работало, данные должны располагаться в мажорном столбце (Fortran-порядок).
Есть еще одна вещь, которую нужно учитывать: способ тестирования производительности. Ваш тестовый массив имеет размер всего около 2 МБ и, следовательно, достаточно мал для кэша L3. Пропускная способность кэша L3 зависит от количества ядер, используемых для расчета, но будет, по крайней мере, около 100 ГБ / с - не намного медленнее, чем GPU, и, вероятно, намного быстрее при распараллеливании на CPU.
Вам нужен больший набор данных, чтобы не обмануться поведением кэша.
Несколько неуместное замечание: ваш алгоритм не очень устойчив с цифровой точки зрения.
Если ширина окна была 3, как в вашем примере, но в строке было около 10**4
элементов. Таким образом, для последнего элемента значение является результатом примерно 10**4
сложений и вычитаний, каждое из которых добавляет к значению ошибку округления - по сравнению только с тремя тремя сложениями, если они сделаны "наивно", это большая разница.
Конечно, это может не иметь значения (для 10 элементов подряд, как в вашем примере), но также может укусить вас однажды ...