Pull to refresh

Comments 13

А может подскажете, почему собственно первый запуск так долго работал? Я правильно понимаю, что всегда первая инициализация ядра куды проходит с задержкой?
Вы правы. Дело в том, что я не упомянул о контекстах CUDA: это некоторый аналог процесса на CPU — каждый контекст имеет свое собственное адресное пространство, а каждый CPU поток работает только с одним CUDA контекстом в конкретный момент времени. Собственно, первая инициализация происходит с задержкой изза ленивого создания контекста.
Это еще что, мы гоняли некую вычислительную программу на серверах, так там первая инициализация могла выполняться секунд 10. Это к тому, что надо строить свой код так, чтобы такая инициализация была ровно одна.
здорово, продолжайте, изучал курс, но скомпилированная и переведенная информация всегда лучше
Если вы приводите в тексте конкретное время расчета задачи в миллисекундах, то наверное нужно обязательно указать также аппаратную и программную конфигурацию машины на которой эти расчеты были выполнены, а еще размер тестовых данных.
Спасибо за замечания — добавил аппаратную конфигурацию и размер тестовых данных в эту статью, учту для следующих. А какую именно программную конфигурацию следует указать — компилятор, версии OpenMP и CUDA?
Операционную систему, версию компилятора, версии OpenMP и CUDA… в общем все то, что может потребоваться для воспроизведения результатов, которые вы измерили.
Добавил. Если что-то упустил — буду рад замечаниям.
Есть замечательное свойство фильтра Гаусса — вместо расчета один раз окном 9x9 можно применить последовательно 4 раза фильтр Гаусса с окном 3x3 и получить тот же результат (если конечно не учитывать ошибки округления).
Как не сложно подсчитать в первом случае будет порядка 81 операций сложения и умножения, а во втором только 36.

Зато второй вариант хуже параллелится и более требователен к пропускной способности памяти (ну и конечно гораздо менее показателен в плане прироста производительности GPU по сравнению с CPU).

Для сравнения результаты работы Гауссова фильтра размера 3x3 для RGB картинки на CPU (i7-4770).

Scalar — 0.853 ms, SSE2 — 0.132 ms, AVX2 — 0.069 ms.

Для корректности сравнения нужно умножить результаты на 4:

Scalar — 3.4 ms, SSE2 — 0.53 ms, AVX2 — 0.28 ms.

По итогу — код на CPU фактически в 10 раз быстрее кода на GPU и это даже без учета необходимости копирования данных. Тут к стати отдельный вопрос почему автор не ипользует ::cudaMallocHost для аллокации памяти на хосте. Это на порядок повысит скорость копирования данных на устройство.

Тут к стати отдельный вопрос почему автор не ипользует ::cudaMallocHost для аллокации памяти на хосте. Это на порядок повысит скорость копирования данных на устройство.

Про pinned memory будет рассказано в следующих частях.
Есть замечательное свойство фильтра Гаусса — вместо расчета один раз окном 9x9 можно применить последовательно 4 раза фильтр Гаусса с окном 3x3 и получить тот же результат (если конечно не учитывать ошибки округления).

Тут Вы, по-моему, ошиблись. Википедия говорит, что применение нескольких, последовательных фильтров с радиусами R1,...,RN эквивалентно применению единого фильтра с радиусом R=sqrt(R12+...+RN2). Так что применение 4-х фильтров с радиусом 3 эквивалентно применению фильтра с радиусом R=sqrt(4*9)=6, а не 9 — нужно применить фильтр с радиусом 3 девять раз, чтобы это было эквивалентно применению фильтра с радиусом 9 один раз.
А в общем — вы сравниваете оптимизированный код на CPU с неоптимизированным кодом на GPU — несколько некорректно, не находите?) Все таки приведенный код на GPU еще тоже есть куда оптимизировать — переместить веса фильтра в константную память, пиксели входного изображения в shared memory, обрабатывать несколько пикселей каждым потоком и т.д. Но я согласен, что и этот пример возможно будет рассчитываться быстрее на CPU, хотя все равно думаю, что для больших изображений GPU вариант должен выигрывать. Для интереса — не могли бы Вы подправить свой вариант, чтобы он выполнял маленький фильтр правильное количество раз, и прогнать его на этом изображении — а я оптимизирую код на GPU, и проверю его время?
Нет. Я правильно подсчитал — можете проверить:

применение фильтра 3х3 два раза подряд приводит к увеличению окна на один пиксел в каждую сторону, соответственно на 2 пикселя всего. 3x3 + 3x3 = 5x5. и т.д.
P.S. Мы оба правы. Радиус гауссова фильтра растет как корень квадратный от количества последовательного примененных фильтров. Но радиус окна фильтра растет линейно до тех пор, пока мы не начинаем пренебрегать его крайними значениями.
Sign up to leave a comment.