Тестирование в математическом приложении FFTW: работа над ошибками

В ходе обсуждения статьи, посвященной использованию пакета FFTW 3.3.5 в роли бенчмарка, выяснилось, что проведенные нами измерения некорректны, поскольку мы фактически измеряли не само время реализации преобразования Фурье, а время планирования этого преобразования, которое не является показательным. Идеология в данном случае следующая. План создается и применяется для фиксированного набора параметров: для определенной размерности преобразования, размера по осям, типа входных и выходных данных, числа потоков, алгоритма преобразования и т. п. Впоследствии этот единожды созданный план применяется десятки тысяч и более раз, так что время создания самого плана совершенно не критично — показательно именно время реализации преобразования.

Кроме того, мы получили ряд конструктивных предложений, которые позволили нам, что называется, довести данный тест «до ума». Собственно, именно для этого мы и выносим на обсуждение методику тестирования заранее, чтобы иметь возможность ее подкорректировать и исправить все ошибки.

Итак, благодаря активному участию наших форумчан (за что им еще раз выражаем свою признательность) тест с использованием пакета FFTW 3.3.5 был полностью переделан. Был заново собран (скомпилирован) пакет FFTW под операционную систему Windows (компилятор GCC 6.1.0). Причем было собрано два отдельных пакета — FP32 (float) и FP64 (double).

При тестировании первоначально создавался файл планирования wis.dat, который затем использовался для реализации самого преобразования Фурье. Для создания файла планирования использовалась команда:

bench -r 1 -t 0.001 -owisdom -opatient -onthreads= [...],

где [...] определяют сами задачи (типы преобразования Фурье).

Созданный файл планирования wis.dat используется в команде запуска теста:

bench -v2 -r -t

В данном случае параметр -r задает количество повторов измерений, а параметр -t задает время одного измерения. За время одного измерения могут осуществляться тысячи преобразований Фурье. Важно, что время выполнения команды практически не зависит от производительности процессора и задается лишь параметрами -r и -t. А вот количество реализованных преобразований за время выполнения команды уже определяется производительностью процессора. В данном случае важно, чтобы за время одного измерения производилось много преобразований Фурье, что позволит точно определить время одного преобразования, с небольшой погрешностью. Для каждой задачи рассчитывается среднее время преобразования, наименьшее и наибольшее время, а также медиана.

Теперь о самой задаче (типе преобразования). Мы экспериментировали с разными типами преобразования (одномерные, двумерные, трехмерные), но в итоге остановились на трехмерном преобразовании icf256x256x256 с использованием пакета FP32 (float). Дело в том, что преобразование icf256x256x256, как утверждают разработчики пакета FFTW, часто используется в практических задачах (двумерное преобразование icf1024x1024, впрочем, тоже, но нам нужно было выбрать что-то одно). Выбор же в пользу пакета FP32 (float) был сделан на том основании, что для него получается меньше разброс результатов.

Резюмируя, для создания файла планирования мы использовали команду:

bench -r 1 -t 0.001 -owisdom -opatient -onthreads= icf256x256x256

а для получения результатов теста — команду:

bench -v2 -r 5 -t 10 -owisdom -owisdom-only -onthreads= icf256x256x256

Количество потоков () соответствовало количеству логических ядер процессора, то есть количеству ядер с учетом Hyper-Threading. В тесте фиксировалось среднее время преобразования Фурье.

Стенд для тестирования не менялся и имел следующую конфигурацию:

  • Процессор: Intel Core i7–6950X (Broadwell-E);
  • Системная плата: Asus Rampage V Edition 10 (Intel X99);
  • Память: 4×4 ГБ DDR4–2400 (Kingston HyperX Predator HX424C12PBK4/16);
  • Видеокарта: Nvidia Quadro 600;
  • Накопитель: SSD Seagate ST480FN0021 (480 ГБ).

Зависимость результатов от количества ядер процессора

Количество используемых в ходе тестирования ядер процессора Intel Core i7–6950X регулировалось через настройки UEFI BIOS платы Asus Rampage V Edition 10. Напомним, что процессор Intel Core i7–6950X является 10-ядерным, но поддерживает технологию Hyper-Threading, поэтому операционной системой и приложениями он видится как 20-ядерный.

Мы не отключали технологию Hyper-Threading и меняли лишь количество физических ядер процессора от 1 до 10. В дальнейшем мы будем говорить о логических ядрах процессора, количество которых менялось от 2 до 20 с шагом 2.

Частота работы всех ядер процессора фиксировалась и составляла 4.0 ГГц.

Результаты тестирования представлены далее:

Как видим, время выполнения преобразования уменьшается обратно пропорционально количеству ядер процессора или, если точнее, количеству запущенных потоков, но с учетом того, что количество запущенных потоков в нашем случае соответствует количеству ядер, это одно и то же.

Вообще, нужно отметить, что используемая нами тестовая задача очень хорошо распараллеливается. В варианте с 20 потоками загружаются на 100% все 20 ядер. Это, конечно же, не означает, что скорость выполнения преобразования 20 потоками будет в десять раз выше, чем 2 потоками, но, тем не менее, зависимость скорости преобразования от количества потоков/ядер является почти линейной (в диапазоне от 2 до 20 ядер).

Зависимость результатов от частоты процессора

Частота ядер процессора Intel Core i7–6950X менялась в настройках UEFI BIOS платы Asus Rampage V Edition 10 путем изменения коэффициента умножения. Частота работы всех ядер процессора фиксировалась (то есть режим Turbo Boost отключался). Использовались все ядра процессора (10 физических/20 логических). Частота менялась от 3,0 ГГц до 4,2 ГГц с шагом 200 МГц.

Результаты тестирования представлены далее:

Как видно по результатам тестирования, время выполнения теста зависит от частоты процессора, однако зависимость довольно слабая: при подъеме частоты процессора с 3 до 4 ГГц (увеличение на 33,3%) время выполнения тестовой задачи уменьшается всего на 8,9%.

Зависимость результатов от частоты памяти

Теперь рассмотрим зависимость скорости выполнения тестовых задач от частоты работы памяти DDR4. Память работала в четырехканальном режиме (по одному модулю на канал), а частота памяти менялась в настройках UEFI BIOS в диапазоне от 1600 МГц до 2800 МГц c шагом в 200 МГц. Тайминги памяти фиксировались и не менялись при изменении частоты. Все ядра процессора работали на частоте 4,0 ГГц.

Результаты тестирования представлены далее:

Как видим, скорость выполнения тестовой задачи очень сильно зависит от скорости работы памяти (это тот редкий случай, когда от памяти что-то зависит). При увеличении частоты памяти с 1600 до 2800 МГц (увеличение на 75%) время выполнения тестовой задачи уменьшается на 33%.

Заключение

Итак, в этой статье мы рассмотрели исправленный тест на основе приложения FFTW 3.3.5, который появился благодаря активному обсуждению на форуме и при помощи активных читателей. Особую признательность хотелось бы выразить Льву Серебрякову (aka Black Lion), который, фактически, и разработал новый тест (начиная от компиляции пакета и заканчивая разработкой методики тестирования).

Также в заключение хотелось бы отметить, что мы пересмотрели результаты тестирования с использованием пакета GNU Octave 4.0.3 и пришли к выводу, что данный тест не подходит для тестирования процессоров и ПК. Во-первых, скрипт, используемый в качестве тестовой задачи (workload), очень плохо распараллеливается, а во-вторых, вникнув детально в суть этого скрипта, мы пришли к выводу, что он не отвечает реальным задачам.

Поэтому в настоящее время мы разрабатываем новый тест с использованием математического пакета MatLab (не FFT). К сожалению, никаких готовых скриптов для MatLab, которые можно было бы использовать в качестве теста, нам найти не удалось.

Сложность заключается в том, чтобы создать скрипт, который, с одной стороны, соответствовал бы реальной задаче, а с другой — выполнялся бы не доли секунд, а несколько минут. Идеи на этот счет есть, но все пока на стадии разработки. Один из возможных вариантов — решение СЛАУ из десятка тысяч уравнений с рандомными коэффициентами методом обратной матрицы. Эта задача хорошо распараллеливается и требует много времени для решения. Но вот насколько она соответствует реальности — это вопрос. Другой возможный вариант — решение трехмерной задачи о колебании мембраны с закрепленными концами с последующей анимацией. В данном случае просчитывается большое количество кадров, что требует значительного времени. Задача также хорошо распараллеливается. Впрочем, не будем забегать вперед.

Если у наших читателей, которые работают с MatLab, есть реальные ресурсоемкие задачи, которыми они готовы поделиться, то, как говорится, welcome aboard.

Полный текст статьи читайте на iXBT