英特尔Phi上的MKL性能

And*_*rew 6 c openmp intel-vtune intel-mkl intel-mic

我有一个例程,在小矩阵(50-100 x 1000个元素)上执行一些MKL调用以适合模型,然后我调用不同的模型.在伪代码中:

double doModelFit(int model, ...) {
   ...
   while( !done ) {
     cblas_dgemm(...);
     cblas_dgemm(...);
     ...
     dgesv(...);
     ...
   }
   return result;
}

int main(int argc, char **argv) {
  ...
  c_start = 1;  c_stop = nmodel;
  for(int c=c_start; c<c_stop; c++) {
    ...
    result = doModelFit(c, ...);
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

调用上面的版本1.由于模型是独立的,我可以使用OpenMP线程来并行化模型拟合,如下所示(版本2):

int main(int argc, char **argv) {
  ...
  int numthreads=omp_max_num_threads();
  int c;
#pragma omp parallel for private(c)
  for(int t=0; t<numthreads; t++) {  
     // assuming nmodel divisible by numthreads...      
     c_start = t*nmodel/numthreads+1; 
     c_end = (t+1)*nmodel/numthreads;
     for(c=c_start; c<c_stop; c++) {
        ...
        result = doModelFit(c, ...);
        ...
     }
  }
}
Run Code Online (Sandbox Code Playgroud)

当我在主机上运行版本1时,它需要大约11秒,而VTune报告的并行化很差,大部分时间都是空闲的.主机上的版本2需要大约5秒钟,而VTune报告了很好的并行化(在使用8个CPU时花费了近100%的时间).现在,当我编译代码以在本机模式下运行Phi卡(使用-mmic)时,在mic0上的命令提示符下运行时,版本1和2都需要大约30秒.当我使用VTune对其进行分析时:

  • 版本1大约需要30秒,热点分析显示大部分时间花在__kmp_wait_sleep和__kmp_static_yield上.在7710秒的CPU时间内,5804秒花费在旋转时间上.
  • 版本2需要fooooorrrreevvvver ...我在VTune运行几分钟后杀了它.热点分析显示,在25254s的CPU时间内,[vmlinux]花费了21585s.

任何人都可以了解这里发生的事情以及为什么我会遇到如此糟糕的表现?我使用OMP_NUM_THREADS的默认值并设置KMP_AFFINITY = compact,granularity = fine(由Intel推荐).我是MKL和OpenMP的新手,所以我确定我犯了新手的错误.

谢谢,安德鲁

Ant*_*ton 1

鉴于大部分时间都花在操作系统 (vmlinux) 上,导致此行为的最可能原因是cblas_dgemm()和的 MKL 实现内嵌套 OpenMP 并行区域导致的过度订阅dgesv。例如看这个例子

此版本由英特尔论坛上的 Jim Dempsey 支持和解释。