Оказалось, что проблема была действительно в задании, как это было предложено Владимиром Ф. и Жилем Гуаиллардетом (большое спасибо!).
Сначала я понял, что использую MPI с OpenMPI версии 1.6.4, а не MVAPICH2, поэтому команда export MV2_ENABLE_AFFINITY=0
не имеет здесь никакого реального значения. Во-вторых, я (предположительно) позаботился о сходстве различных потоков OpenMP, установив
export OMP_PROC_BIND=true
export OMP_PLACES=cores
, но не устанавливал правильные привязки для процессов MPI, так как неправильно запускал приложение как
mpirun -np 2 ./Par2S
и, похоже, что с OpenMPI версии 1.6.4, более подходящий способ сделать это -
mpirun -np 2 -bind-to-core -bycore -cpus-per-proc 2 ./hParP2S
Команда -bind-to-core -bycore -cpus-per-proc 2
обеспечивает 2 ядра для моего приложения (см. https://www.open -mpi.org / doc / v1.6 / man1 / mpirun.1.php , а также комментарии Жиля Гуаиллардета к Убедитесь, что гибридный MPI / OpenMP запускает каждый поток OpenMP на отдельном ядре ). Без этого оба MPI-процесса собирались в одно ядро, что стало причиной низкой эффективности кода, когда в Makefile использовался флаг -fopenmp
.
Очевидно, что при запуске чистого MPI-кода, скомпилированного без флага -fopenmp
, различные MPI-процессы автоматически переходят на разные ядра, но при -fopenmp
необходимо указывать привязки вручную, как описано выше.
В целях полноты я должен упомянуть, что не существует стандарта для установки правильного соответствия задач, поэтому мое решение не будет работать, например, с MVAPICH2 или (возможно) с различными версиями OpenMPI. Кроме того, для выполнения nproc процессов MPI с nthreads каждый в ncores ЦП потребуется, например,
export OMP_PROC_BIND=true
export OMP_PLACES=cores
export OMP_NUM_THREADS=nthreads
mpirun -np nproc -bind-to-core -bycore -cpus-per-proc ncores ./hParP2S
, где ncores = nproc * nthreads.
пс: мой код имеет MPI_all_to_all. Условие, когда более одного процесса MPI находятся на одном ядре (без гиперпоточности), вызывающего эту подпрограмму, должно быть причиной того, что код был примерно в 100 раз медленнее.