系统规格:
- Intel Xeon E7-v3 处理器(4 插槽,16 核/插槽,2 线程/核)
- 使用 Eigen 族和 C++
以下是代码片段的串行实现:
Eigen::VectorXd get_Row(const int j, const int nColStart, const int nCols) {
Eigen::VectorXd row(nCols);
for (int k=0; k<nCols; ++k) {
row(k) = get_Matrix_Entry(j,k+nColStart);
}
}
double get_Matrix_Entry(int x , int y){
return exp(-(x-y)*(x-y));
}
我需要并行化 get_Row 部分,因为 nCols 可以大到 10^6,因此,我尝试了某些技术:
朴素的并行化:
Eigen::VectorXd get_Row(const int j, const int nColStart, const int nCols) { Eigen::VectorXd row(nCols); #pragma omp parallel for schedule(static,8) for (int k=0; k<nCols; ++k) { row(k) = get_Matrix_Entry(j,k+nColStart); return row; }
条带采矿:
Eigen::VectorXd get_Row(const int j, const int nColStart, const int nCols) { int vec_len = 8; Eigen::VectorXd row(nCols) ; int i,cols; cols=nCols; int rem = cols%vec_len; if(rem!=0) cols-=rem; #pragma omp parallel for for(int ii=0;ii<cols; ii+=vec_len){ for(i=ii;i<ii+vec_len;i++){ row(i) = get_Matrix_Entry(j,i+nColStart); } } for(int jj=i; jj<nCols;jj++) row(jj) = get_Matrix_Entry(j,jj+nColStart); return row; }
来自互联网的某个地方以避免虚假共享:
Eigen::VectorXd get_Row(const int j, const int nColStart, const int nCols) { int cache_line_size=8; Eigen::MatrixXd row_m(nCols,cache_line_size); #pragma omp parallel for schedule(static,1) for (int k=0; k<nCols; ++k) row_m(k,0) = get_Matrix_Entry(j,k+nColStart); Eigen::VectorXd row(nCols); row = row_m.block(0,0,nCols,1); return row; }
输出:
上述技术都没有帮助减少大型 nCol 执行 get_row 所需的时间,这意味着简单的并行化与其他技术类似(尽管串行更好),有什么建议或方法可以帮助改善时间吗?
正如用户 Avi Ginsburg 所说,我提到了其他一些系统细节:
- g++(GCC) 是 4.4.7 版本的编译器
- 特征库版本为 3.3.2
- 使用的编译器标志:“-c -fopenmp -Wall -march=native -O3 -funroll-all-loops -ffast-math -ffinite-math-only -I header”,这里的 header 是包含 Eigen 的文件夹。
gcc -march=native -Q --help=target->的输出(仅提及一些标志的描述):
-mavx [启用]
-mfancy-math-387 [启用]
-mfma [已禁用]
-三月=核心2
有关标志的完整说明,请参阅此。