我在 FORTRAN 中实现了共轭梯度,将维基百科示例中的线性代数子例程替换为(Fortran)英特尔 MKL 子例程。(仅限DGEMV,DAXPY和DNRM。事实证明,a=b 比 DCOPY 快,a=2*a 比 DSCAL 快)
答案是正确的,实现没有问题。但是,当我将其编译为ifort CG.f90 -mkl
时,结果是:
MKL_SET_DYNAMIC = 真;140 秒
MKL_SET_DYNAMIC = FALSE,MKL_SET_NUM_THREADS=1 ;70 秒。
MKL_SET_DYNAMIC = FALSE, MKL_SET_NUM_THREADS=2 ; ~100 秒。
几点:
- 通过超线程,我有 2 个真实内核和 2 个虚拟内核。我不是在尝试在 16 核机器上运行 2 个线程。
- 分析产生了对
M16_LAY_GAS16
的深奥引用,经过大量搜索后,该multpd
归结为ASM。否则没有任何有用的结果(或者也许,我不知道去哪里看)FWIW,我使用了 VTune。 - 问题大小不小。以上示例适用于与我的 RAM 大小成比例的矩阵大小(对于我的 4 GB 系统,大约为 13k x 13k)。
-
KMP_AFFINITY
将串行情况下的一个线程映射到一个处理器,将两个线程并行映射到两个处理器。
我的问题是:如果这是最佳的,为什么MKL_DYNAMIC线程数不设置为 1?如果相同的工作(在更短的时间内)由 1 完成,我不一定需要使用 2 个线程。
是我做错了什么,还是英特尔 MKL 出了问题?
MKL_DYNAMIC
在功能上与OpenMP标准的OMP_DYNAMIC
/omp_set_dynamic()
相同。
这并不意味着"神奇地更改线程数以尽可能快地运行代码"。这意味着在某些情况下,如果有系统资源或其他实现特定原因,运行时可以从用户指定的值或系统默认值更改线程数。鉴于您没有指定多个线程并且有 4 个并发硬件线程可用,我猜您的MKL_SET_DYNAMIC = TRUE
情况使用的是四个线程。
如果您运行类似 MKL_SET_DYNAMIC=TRUE MKL_SET_NUM_THREADS=16
的操作,您可能会发现运行时将线程计数限制为 4,并且性能会优于 MKL_SET_DYNAMIC=FALSE MKL_SET_NUM_THREADS=16
,因为运行时可能会检测到您请求的不仅仅是可用并发硬件线程数。但这就是我所期望的。