Извините за длинный пост, но я хотел включить все, что я думал, было актуально с первого взгляда.
Что я хочу
Я реализую параллельную версию методов подпространств Крылова для плотных матриц. В основном GMRES, QMR и CG. Я понял (после профилирования), что моя рутина DGEMV была жалкой. Поэтому я решил сосредоточиться на этом, изолируя его. Я попытался запустить его на 12-ядерном компьютере, но ниже приведены результаты для 4-ядерного ноутбука Intel i3. В тенденции не так много различий.
Мой KMP_AFFINITY=VERBOSE
вывод доступен здесь .
Я написал небольшой код:
size_N = 15000
A = randomly_generated_dense_matrix(size_N,size_N); %Condition Number is not bad
b = randomly_generated_dense_vector(size_N);
for it=1:n_times %n_times I kept at 50
x = Matrix_Vector_Multi(A,b);
end
Я считаю, что это имитирует поведение CG в течение 50 итераций.
Что я пробовал:
Перевод
Я изначально написал код на Фортране. Я перевел это на C, MATLAB и Python (Numpy). Само собой разумеется, MATLAB и Python были ужасны. Удивительно, но C был лучше, чем FORTRAN на секунду или две для вышеуказанных значений. Последовательно.
Профилирование
Я профилировал свой код для запуска, и он работал в течение 46.075
нескольких секунд. Это было, когда MKL_DYNAMIC был установлен вFALSE
и все ядра были использованы. Если бы я использовал MKL_DYNAMIC как истину, то в любой момент времени использовалась только (приблизительно) половина количества ядер. Вот несколько деталей:
Address Line Assembly CPU Time
0x5cb51c mulpd %xmm9, %xmm14 36.591s
Наиболее трудоемким процессом представляется:
Call Stack LAX16_N4_Loop_M16gas_1
CPU Time by Utilization 157.926s
CPU Time:Total by Utilization 94.1%
Overhead Time 0us
Overhead Time:Total 0.0%
Module libmkl_mc3.so
Вот несколько изображений:
Выводы:
Я настоящий новичок в профилировании, но я понимаю, что ускорение все еще не хорошо. Последовательный (1-ядерный) код завершается за 53 секунды. Это скорость меньше, чем 1,1!
Реальный вопрос: что я должен сделать, чтобы улучшить свое ускорение?
Вещи, которые, я думаю, могут помочь, но я не уверен:
- Реализация Pthreads
- Реализация MPI (ScaLapack)
- Ручная настройка (я не знаю, как. Пожалуйста, порекомендуйте ресурс, если вы предлагаете это)
Если кому-то нужно больше (особенно в отношении памяти) деталей, пожалуйста, дайте мне знать, что мне следует запускать и как. У меня никогда не было профилированной памяти раньше.
источник
Как дела умножение матрицы на вектор? Двойной цикл вручную? Или звонки в BLAS? Если вы используете MKL, я настоятельно рекомендую использовать подпрограммы BLAS в многопоточной версии.
Из любопытства вы также можете скомпилировать собственную настроенную версию ATLAS и посмотреть, как это отразится на вашей проблеме.
Обновить
После обсуждения в комментариях ниже выясняется, что ваш Intel Core i3-330M имеет только два «настоящих» ядра. Два недостающих ядра эмулируются с гиперпоточностью . Поскольку в многопоточных ядрах и шина памяти, и модули с плавающей запятой являются общими, вы не получите никакого ускорения, если какой-либо из этих двух факторов является ограничивающим фактором. Фактически, использование четырех ядер может даже замедлить работу.
Какие результаты вы получаете на «только» двух ядрах?
источник
У меня сложилось впечатление, что упорядочение по основным строкам оптимально для этой проблемы с точки зрения времени доступа к памяти, использования строк кэша и пропусков TLB. Я предполагаю, что ваша версия FORTRAN вместо этого использовала упорядочение по основным столбцам, что могло бы объяснить, почему оно неизменно медленнее, чем версия C.
Вы также можете проверить скорость, если вы просто суммируете все элементы матрицы в одном цикле вместо умножения вектора матрицы. (Возможно, вы захотите развернуть цикл в 4 раза, потому что неассоциативность сложения может помешать компилятору выполнить эту оптимизацию за вас.)
источник