我们正在编写一个性能至关重要的应用程序,它具有3个主要参数: N_steps(大约10000) N_nodes(20到5000之间的任何值) N_size(范围大约1k-10k)
算法本质上是这种形式
for (int i=0; i<N_steps; i++)
{
serial_function(i);
parallel_function(i,N_nodes);
}
其中
parallel_function(i,N_nodes) {
#pragma omp parallel for schedule (static) num_threads(threadNum)
for (int j=0; j<N_nodes j++)
{
Local_parallel_function(i,j) //complexity proportional to N_size
}
}
和Local_parallel_function是执行线性代数的函数,它通常具有约0.01-0.04秒甚至更长的运行时间,并且此执行时间在循环内应该非常稳定。不幸的是,这个问题本质上是顺序的,所以我不能以不同的方式编写外循环。
我在分析时注意到,NtYieldExecution函数花费了大量时间(如果在4个内核上使用HT,则最多会花费20%)。
我对参数进行了一些测试,发现这个百分比:
增加线程数
随着N_nodes和N_size的增加而减小。
对于OpenMP来说,并行循环目前最有可能不够大,而使其增大或使该函数的计算成本更高有助于减少这种开销。
为了获得更好的见解,我下载了Intel Profiler,并获得了以下结果:
红色区域是旋转时间,顶部的线程是OpenMP产生的旋转时间。
关于如何管理和减少这种影响的任何建议?
我使用Windows 10,Visual Studio 15.9.5和OpenMP。不幸的是,英特尔编译器似乎无法编译一个依赖库,因此我只能使用微软的依赖库。