Я пытаюсь сравнить три разных приложения. Все они написаны на C ++ с использованием MPI и OpenMP и скомпилированы с gcc7.1 и OpenMPI3.0. Я использую кластер с несколькими узлами и 2 процессорами Intel с 24 ядрами. На каждом узле выполняется один процесс, и на каждом узле распараллеливание выполняется с помощью OpenMP.
Изменить: Это самый короткий тест, я тестировал пользовательские операции сокращения:
#include <mpi.h>
#include <omp.h>
#include <vector>
#include <chrono>
int process_id = -1;
std::vector<double> values(268435456, 0.1);
void sum(void *in, void *inout, int *len, MPI_Datatype *dptr){
double* inv = static_cast<double*>(in);
double* inoutv = static_cast<double*>(inout);
*inoutv = *inoutv + *inv;
}
int main(int argc, char** argv) {
MPI_Init(&argc, &argv);
int mpi_world_size = 0;
MPI_Comm_size(MPI_COMM_WORLD, &mpi_world_size);
MPI_Comm_rank(MPI_COMM_WORLD, &process_id);
#pragma omp declare reduction(sum : double : omp_out = omp_out + omp_in) initializer(omp_priv = omp_orig)
MPI_Op sum_mpi_op;
MPI_Op_create( sum, 0, &sum_mpi_op );
double tmp_result = 0.0;
double result = 0.0;
std::chrono::high_resolution_clock::time_point timer_start = std::chrono::high_resolution_clock::now();
#pragma omp parallel for simd reduction(sum:tmp_result)
for(size_t counter = 0; counter < 268435456; ++counter){
tmp_result = tmp_result + values[counter];
}
MPI_Allreduce(&tmp_result, &result, sizeof(double), MPI_BYTE, sum_mpi_op, MPI_COMM_WORLD);
std::chrono::high_resolution_clock::time_point timer_end = std::chrono::high_resolution_clock::now();
double seconds = std::chrono::duration<double>(timer_end - timer_start).count();
if(process_id == 0){
printf("Result: %.5f; Execution time: %.5fs\n", result, seconds);
}
MPI_Finalize();
return EXIT_SUCCESS;
}
Я заметил, что время выполнения для всех тестов варьируется между двумя значениями, например, для теста A у меня 10 пробежек, 5 — около 0,6 с, а 5 — около 0,73 (+/- немного).
Для Benchmark B это то же самое, но время исполнения составляет 77 с или 85 с (снова +/-).
Эквивалентные результаты для Benchmark C. Таким образом, между ними нет ничего.
Я измеряю время с помощью std :: chrono: high_resolution_clock:
std::chrono::high_resolution_clock::time_point timer_start = std::chrono::high_resolution_clock::now();
// do something
std::chrono::high_resolution_clock::time_point timer_end = std::chrono::high_resolution_clock::now();
double seconds = std::chrono::duration<double>(timer_end - timer_start).count();
Slurm используется в качестве пакетной системы, и я использую эксклюзивную опцию, чтобы убедиться, что на узлах не выполняются другие задания.
Для работы Slurm я использую в основном следующий файл:
#!/bin/bash
#SBATCH --ntasks 4
#SBATCH --nodes 4
#SBATCH --ntasks-per-node 1
#SBATCH --exclusive
#SBATCH --cpus-per-task 24
export OMP_NUM_THREADS=24
RUNS=10
for ((i=1;i<=RUNS;i++)); do
srun /path/bench_a
done
Для сборки кода я использую CMake и устанавливаю флаги
-O3 -DNDEBUG -march=haswell -DMPICH_IGNORE_CXX_SEEK -std=c++14
Поскольку он одинаков для всех тестов, я не верю, что причина в реализации, а в том, как я строю код или начинаю работу.
Ты хоть представляешь, что мне следует искать, чтобы объяснить это поведение?
Спасибо
Это обычная проблема для бенчмаркинга …
Обычно тесты выполняются 10 000 раз, а затем усредняются. Колебания времени исполнения ниже 10% трудно избежать.
В вашем кластере только 4 узла?
Причиной, которая может объяснить это, является использование сети, особенно если время связи на самом деле составляет довольно большой процент времени выполнения (поскольку вы можете быть не единственным, работающим в то время в кластере). Единственный способ избежать этой проблемы — запустить эталонный тест со всем кластером или в резервировании всего кластера. Вы должны спросить ИТ, что они предпочитают, особенно если у вас есть определенный бюджет в кластере. Но обычно 10 000 прогонов дают довольно хорошую оценку времени выполнения.
(вы правы насчет множественного srun в данном скрипте slurm, всегда запускайте все тесты, которые вы хотите сравнить в одном скрипте :-))
Других решений пока нет …