Я разрабатываю код с большой плотной матрицей. Когда я просматриваю код, он иногда получает около 75% пиковых нагрузок моей четырехъядерной системы, а в других случаях - около 36%. Эффективность не изменяется между выполнением кода. Он либо начинается с 75%, либо продолжает свою эффективность, либо начинается с 36% и продолжает эту эффективность.
Я проследил проблему до гиперпоточности и тот факт, что я установил число потоков на четыре вместо восьми по умолчанию. Когда я отключу гиперпоточку в BIOS, я получаю примерно 75% эффективности последовательно (или, по крайней мере, я никогда не вижу резкого падения до 36%).
Перед вызовом любого параллельного кода я делаю omp_set_num_threads(4)
. Я также пробовал export OMP_NUM_THREADS=4
, прежде чем запускать свой код, но он кажется эквивалентным.
Я не хочу отключать гиперпоточность в BIOS. Я думаю, мне нужно связать четыре потока с четырьмя ядрами. Я тестировал несколько разных случаев GOMP_CPU_AFFINITY
, но до сих пор у меня все еще есть проблема, что эффективность составляет 36%. Что такое сопоставление с гиперпотоками и ядрами?. do thread 0 и thread 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"
или
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