基准问题:执行时间在两个值之间变化

时间:2018-04-09 15:32:52

标签: c++ mpi openmp benchmarking slurm

我正在尝试对三种不同的应用程序进行基准测试所有这些都是使用MPI和OpenMP用C ++编写的,并使用gcc7.1和OpenMPI3.0编译。我使用具有多个节点的集群和2个具有24个核心的Intel CPU。每个节点上都运行一个进程,并且每个节点都使用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.6s,5次约0.73s(+/-一点)。 对于基准B,它是相同的,但执行时间是77s或85s(再次+/-)。 基准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

由于所有基准测试都是相同的,我不相信原因是实现,而是我构建代码或开始工作的方式。

你知道我应该寻找什么来解释这种行为吗? 谢谢

1 个答案:

答案 0 :(得分:-1)

这是基准测试的常见问题...... 通常基准测试执行10'000次然后平均。执行时间波动10%以下很难避免。

您的群集只有4个节点吗? 可以解释它的原因是网络使用,特别是如果通信时间实际上是执行时间的相当大的百分比(因为您可能不是当时在群集上运行的唯一一个)。避免此问题的唯一方法是使用整个群集或在整个群集的预留中运行基准测试。您应该询问IT他们喜欢什么,特别是如果您在群集上有预算。但通常10'000次运行可以很好地估计你的执行时间。

(你对于给定的slurm脚本中的多个srun是正确的,在同一个脚本中始终运行你想要比较的所有基准: - )