Я разрабатываю большой плотный матричный код умножения. Когда я профилирую код, он иногда получает около 75% пиковых провалов моей четырехъядерной системы, а иногда около 36%. Эффективность не меняется между выполнениями кода. Он либо начинается с 75% и продолжается с той же эффективностью, либо начинается с 36% и продолжается с той же эффективностью.
Я проследил проблему до гиперпоточности и того факта, что я установил количество потоков равным четырем вместо восьми по умолчанию. Когда я отключаю гиперпоточность в BIOS, я постоянно получаю около 75% эффективности (по крайней мере, я никогда не видел резкого падения до 36%).
Перед вызовом любого параллельного кода я делаю omp_set_num_threads(4)
. Я также пробовал export OMP_NUM_THREADS=4
перед запуском своего кода, но он кажется эквивалентным.
Я не хочу отключать гиперпоточность в биосе. Я думаю, мне нужно привязать четыре потока к четырем ядрам. Я тестировал несколько разных случаев GOMP_CPU_AFFINITY
, но до сих пор у меня все еще есть проблема, что иногда эффективность составляет 36%. Какое сопоставление с гиперпоточностью и ядрами? Например. поток 0 и поток 1 соответствуют одному и тому же ядру, а поток 2 и поток 3 — другому ядру?
Как привязать потоки к каждому ядру без переноса потоков, чтобы мне не приходилось отключать гиперпоточность в BIOS? Возможно, мне нужно изучить возможность использования sched_setaffinity?
Некоторые детали моей текущей системы: ядро Linux 3.13, GCC 4.8, Intel Xeon E5-1620 (четыре физических ядра, восемь гиперпотоков).
Изменить: пока это работает хорошо
export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7"
or
export GOMP_CPU_AFFINITY="0-7"
Изменить: это, кажется, также хорошо работает
export OMP_PROC_BIND=true
Изменить: Эти параметры также работают хорошо (gemm — это имя моего исполняемого файла)
numactl -C 0,1,2,3 ./gemm
и
taskset -c 0,1,2,3 ./gemm
hwloc-ls
из библиотеки hwloc, иcpuinfo
из Intel MPI предоставляют важную информацию о топологии машины, например. сопоставление логических номеров ЦП с физическими ядрами/потоками. Нумерация зависит от BIOS, но, по моему опыту, в большинстве случаев гиперпотоки зацикливаются во внешнем цикле. Кроме того, вы можете использовать сокращенное обозначение"0-7"
. - person Hristo Iliev   schedule 24.06.2014export OMP_PLACES=cores
из OpenMP4.0. В системах AMD каждый модуль имеет только один FPU, но получает два потока, и я думаю, что он назначается линейно stackoverflow.com/questions/19780554/ поэтому я думаю, что GOMP_CPU_AFFINITY=0-7 не сработает. На самом деле, OMP_PROC_BIND=true тоже может подойти. Может быть, это лучшее решение. - person Z boson   schedule 24.06.2014"0-7"
совпадает с"0 1 2 3 4 5 6 7"
. С libgompOMP_PROC_BIND=true
практически не отличается отGOMP_CPU_AFFINITY="0-(#cpus-1)"
, т.е. нет понимания топологии, по крайней мере, для версий до 4.9. - person Hristo Iliev   schedule 24.06.2014OMP_PROC_BIND
включает какую-то привязку, специфичную для реализации. Функция places в OpenMP 4.0 предоставляет пользователю возможность управлять этой привязкой абстрактным образом. В реализациях до версии 4.0 вы должны запуститьhwloc-ls
илиcpuinfo
, чтобы получить актуальную топологию (или проанализировать/proc/cpuinfo
самостоятельно). - person Hristo Iliev   schedule 24.06.2014KMP_AFFINITY=granularity=fine,scatter
с ICC. Это то, что я хочу от процессоров Intel. Я не знаю, какова топология AMD, но я думаю, что ядра AMD на самом деле рассматриваются как отдельные ядра (они предназначены для целых чисел, но не для чисел с плавающей запятой) и не осведомлены о модулях. Это означает, что я должен сделать что-то другое для систем AMD. Это раздражает. - person Z boson   schedule 24.06.2014