Низкая производительность из-за гиперпоточности с OpenMP: как привязать потоки к ядрам

Я разрабатываю большой код умножения плотной матрицы. Когда я профилирую код, он иногда получает около 75% пиковых провалов в моей четырехъядерной системе, а иногда - около 36%. Эффективность не меняется между выполнениями кода. Он либо начинается с 75% и продолжается с этой эффективностью, либо начинается с 36% и продолжается с этой эффективностью.

Я проследил проблему до гиперпоточности и того факта, что я установил число потоков равным четырем вместо восьми по умолчанию.Когда я отключаю гиперпоточность в BIOS, я получаю примерно 75% эффективности (или, по крайней мере, я никогда не вижу резкого падения до 36%).

Прежде чем я вызову любой параллельный код, я делаюomp_set_num_threads(4), Я также пыталсяexport OMP_NUM_THREADS=4 прежде чем я запускаю свой код, но он кажется эквивалентным.

Я не хочу отключать гиперпоточность в BIOS. Я думаю, что мне нужно привязать четыре потока к четырем ядрам. Я проверил несколько разных случаевGOMP_CPU_AFFINITY но до сих пор у меня есть проблема, что эффективность иногда составляет 36%.Что такое отображение с гиперпоточностью и ядрами? Например. соответствуют ли нить 0 и нить одному и тому же ядру, а нить 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

Ответы на вопрос(1)

Ваш ответ на вопрос