我有一个例程,可以在小矩阵(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, ...);
...
}
}
调用上面的版本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, ...);
...
}
}
}
当我在主机上运行版本1时,需要大约11秒,而VTune报告的并行化很差,大部分时间都是闲置的。主机上的版本2需要大约5秒钟,而VTune报告了很好的并行化(在使用8个CPU时花费了近100%的时间)。现在,当我编译代码以在本机模式下运行Phi卡(使用-mmic)时,在mic0上的命令提示符下运行时,版本1和2都需要大约30秒。当我使用VTune对其进行分析时:
任何人都可以了解这里发生的事情以及为什么我会遇到如此糟糕的表现?我正在使用OMP_NUM_THREADS的默认值并设置KMP_AFFINITY = compact,granularity = fine(由Intel推荐)。我是MKL和OpenMP的新手,所以我肯定我犯了新手的错误。
谢谢, 安德鲁
答案 0 :(得分:1)
这种行为最可能的原因是大部分时间花在OS(vmlinux)上,是由cblas_dgemm()
和dgesv
的MKL实现中嵌套的OpenMP并行区域引起的超额预订。例如。见this example。
此版本由Jim Dempsey在Intel forum支持和解释。
答案 1 :(得分:0)
使用MKL怎么样:顺序库?如果将MKL库与顺序选项链接,则它不会在MKL本身内部生成OpenMP线程。我想你可能会比现在更好。