簡體   English   中英

如何使用 Eigen 在 C++ 中多線程此代碼片段

[英]How can I multithread this code snippet in C++ with Eigen

我正在嘗試實現以下代碼片段的更快版本:

Eigen::VectorXd dTX = (( (XPSF.array() - x0).square() + (ZPSF.array() - z0).square() ).sqrt() + txShift)*fs/c + t0*fs;
Eigen::VectorXd Zsq = ZPSF.array().square();   
Eigen::MatrixXd idxt(XPSF.size(),nc);
        
for (int i = 0; i < nc; i++) {
      idxt.col(i) = ((XPSF.array() - xe(i)).square() + Zsq.array()).sqrt()*fs/c + dTX.array();
      idxt.col(i) = (abs(XPSF.array()-xe(i)) <= ZPSF.array()*0.5/fnumber).select(idxt.col(i),-1);
}

我現在正在使用的樣本數組大小是:

XPSF:591*192 系數的列向量(列向量中總計 113,472 個值)

ZPSF:與 XPSF 大小相同

xe:192 個系數的 RowVector

idxt:113,472x192 大小的矩陣

當前使用 gcc 和 -msse2 和 -o3 優化運行,循環第一行的平均時間為 ~0.08 秒,循環第二行的平均時間為 ~0.03 秒。 我知道運行時依賴於平台,但我相信這仍然可以更快。 一個商業軟件在大約兩個數量級的時間內執行我試圖在這里做的操作。 另外,我懷疑我的代碼現在有點業余!

我嘗試通讀 Eigen 文檔以了解矢量化的工作原理、實現位置以及 Eigen 可能“隱式”並行化了多少代碼,但我一直在努力跟蹤細節。 總的來說,我對 C++ 也有點陌生,但我已經看過有關 std::thread 的文檔和其他資源,並嘗試將其與此代碼結合使用,但沒有取得太大成功。

任何意見,將不勝感激。

更新:

這是 dxdiag 對評論的回應的輸出

如果您的 CPU 有足夠多的內核和線程,通常一個簡單快捷的第一步是通過添加編譯指示來調用 OpenMP:

#pragma omp parallel for
for (int i = 0; i < nc; i++)

並使用/openmp -fopenmp (cl) 或-fopenmp (gcc) 或僅使用 gcc 編譯-ftree-parallelize-loops以自動展開循環。

使用本征,您需要添加

OMP_NUM_THREADS=n ./my_program
omp_set_num_threads(n);
Eigen::setNbThreads(n);

https://eigen.tuxfamily.org/dox/TopicMultiThreading.html

但是,在常見問題解答中

目前 Eigen 僅並行化一般的矩陣-矩陣產品(工作台),因此它本身並沒有充分利用並行硬件。”

一般來說,OpenMP 的改進並不總是在這里,因此對發布版本進行基准測試。 另一種方法是確保您使用的是矢量化指令。

再次,從常見問題/矢量化

如何啟用矢量化?

您只需要告訴編譯器啟用相應的指令集,然后 Eigen 就會檢測到它。 如果它默認啟用,那么您不需要做任何事情。 在 GCC 和 clang 上,您只需傳遞 -march=native 即可讓編譯器啟用 CPU 支持的所有指令集。

在 x86 架構上,大多數編譯器默認不啟用 SSE。 您需要手動啟用 SSE2(或更新版本)。 例如,對於 GCC,您將傳遞 -msse2 命令行選項。

在 x86-64 架構上,SSE2 一般是默認開啟的,但是你可以開啟 AVX 和 FMA 以獲得更好的性能

在 PowerPC 上,您必須使用以下標志:-maltivec -mabi=altivec,用於 AltiVec,或 -mvsx 用於支持 VSX 的系統。

在 32 位 ARM NEON 上,以下內容: -mfpu=neon -mfloat-abi=softfp|hard,具體取決於您是否在 softfp/hardfp 系統上。 當前的大多數發行版都使用硬浮點 ABI,因此選擇后者,或者保留默認值並通過 -mfpu=neon。

在 64 位 ARM 上,默認情況下啟用 SIMD,您無需執行任何額外操作。

在 S390X SIMD (ZVector) 上,您必須使用最新的 gcc(版本 >5.2.1)編譯器,並添加以下標志:-march=z13 -mzvector。

考慮到數組的大小,您想嘗試卸載到 GPU 以達到微秒; 在這種情況下,您(通常)將擁有與數組中元素數量一樣多的線程。 一個簡單的開始,如果你有一個 nvidia 卡,你想看看cublas ,它也允許你使用上一代的張量寄存器(融合乘法加法等),與常規內核不同。 您也可以使用常規內核“手動”實現所有內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM