【发布时间】:2020-05-10 09:02:35
【问题描述】:
在我的代码中多次使用以下类型的循环:
#pragma omp parallel for schedule(dynamic, num_threads)
for(int i=0; i<F_matrix_A.size(); i++){
for(int j=0; j<F_matrix_A.size(); j++){
F_previous_T[i][j] = F_previous[j][i];
}
}
#pragma omp parallel for schedule(dynamic, num_threads)
for(int i=0; i<F_matrix_A.size(); i++){
for(int k=0; k<F_matrix_A.size(); k++){
for(int j=0; j<=i; j++){
if(F_previous_T[i][k] != 0 && F_previous[k][j] !=0){
Fisher_new[i][j] += F_previous_T[i][k]*F_previous[k][j];
}
}
}
}
当我在参数之前设置时,我得到了最好的性能:#define num_threads 1
我在一个 64 核的工作站上工作(当我执行 /proc/cpuinfo 时,我看到了 128 个处理器)。我觉得不能从这么多的进程中受益是很遗憾的。
是不是因为我使用了特定的编译指示:
#pragma omp parallel for schedule(dynamic, num_threads)
??
还有其他方法可以缩短运行时间吗?我在不同的论坛上看到,使用大量进程可能会导致大量开销。
我的循环大小通常为 1700x1700。
如果有人有想法,就说出来就好了。
更新 1:我的代码有 2 个版本,一个带有 GNU g++,另一个带有 Intel icpc
1) 我正在使用 Makefile 后面的“通用”:
ifneq "$(MAKECMDGOALS)" "clean"
include $(MAKECMDGOALS).make
endif
OBJECTS = $(SOURCES:.cpp=.o)
$(MAKECMDGOALS): $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CXX) $(LDFLAGS) $(OBJECTS) -o $@
.cpp.o:
$(CXX) $(CXXFLAGS) $(LDFLAGS) $< -o $@
clean:
rm -f *.o
1) 对于GNU g++,我使用gnu.make 文件编译:
CXX = g++ -std=c++11 -O3 -fopenmp
CXXFLAGS = -Wall -c
LDFLAGS = -march=native
LDFLAGS =
SOURCES = main.cpp TSAF_gnu.cpp
EXECUTABLE = main_gnu.exe
2) 对于Intel icpc,我使用intel.make 文件编译:
CXX = icpc -std=c++11 -O3 -xHost -qopenmp
CXXFLAGS = -Wall -c -I${MKLROOT}/include
LDFLAGS = -mkl=parallel
LDFLAGS += -L${MKLROOT}/lib/intel64_lin -Wl,-rpath,${MKLROOT}/lib/intel64_lin -lmkl_intel_lp64 -lmkl_intel_thread \
-lmkl_core -liomp5 -lpthread
SOURCES = main.cpp TSAF_intel.cpp
EXECUTABLE = main_intel.exe
标准运行大约需要 3 分钟。
【问题讨论】:
-
什么是编译标志?您使用哪个优化级别?此外,这种大小的矩阵对于并行处理来说可能太小了。单线程运行需要多长时间?
-
@DanielLangr 我添加了一个 UPDATE 1 为您提供更多信息。
-
一目了然:(1) 你几乎不能编写对缓存不友好的访问模式,遍历一个数组行优先和另一个列优先。 (2) 每个循环的“计算负载”是微不足道的。 (3)
if隐藏在深层循环嵌套底部的语句是一种以非常高的速率混淆分支预测的好方法。 (4)schedule(dynamic, *small_chunk_size*)可能是解决问题的最糟糕的时间表。现在,对于您的应用程序来说,这些都可能无法避免,但您所写的几乎是一个教科书示例,说明何时不 使用 OpenMP。 -
您如何摆脱最内层循环中的
if (...)并废弃schedule子句?如果两个因子中的任何一个为零,则乘积无论如何都将为零,并且乘法非常快。此外,schedule(dynamic)有 HUGE 开销。
标签: c++ multithreading optimization openmp intel