4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenBLASより速くできるか?AMD Ryzen 5 7530Uで3つのアプローチを試した

4
Posted at

前回(第1弾第2弾)では、C++ 4種 + Rust 4種の行列積ベンチマーク比較を行い、OpenBLAS が圧倒的に速いという結論に至った。

では、そのOpenBLASをさらに速くすることはできるのか?
AMD Ryzen 5 7530U(Zen 3 / WSL2環境)で3つのアプローチを試した。


環境

  • CPU: AMD Ryzen 5 7530U(Zen 3、6コア12スレッド)
  • 実行環境: WSL2(2コア4スレッドが割り当て)
  • OS: Ubuntu on WSL2
  • コンパイラ: GCC、-O3 -march=native
  • OpenBLAS: 0.3.20(ZENカーネル入り)
  • 行列サイズ: N = 512 / 1024 / 2048(double精度、各3回中央値)

ベースライン(前回結果):

実装 N=2048
OpenBLAS DGEMM(C++) 206 ms
OpenBLAS cblas FFI(Rust) 178 ms

アプローチ 1:OpenBLASのスレッド数チューニング

動機

OpenBLASはデフォルトで利用可能なコア数を使う。しかしスレッド数が多ければ速いとは限らない。WSL2のオーバーヘッド・ハイパーバイザー越しのスケジューリングにより、スレッド競合が発生する可能性がある。

openblas_set_num_threads() でスレッド数を明示的に制御して計測した。

extern "C" void openblas_set_num_threads(int num_threads);

// 計測前に設定
openblas_set_num_threads(threads);

結果

スレッド数 N=512 N=1024 N=2048
1 11.8 ms 49.7 ms 386.1 ms
2 3.4 ms 28.3 ms 229.2 ms
4 1.9 ms 28.0 ms 170.9 ms

考察

4スレッドで 170.9ms(従来C++比 1.21倍速)。
デフォルト設定(C++の206ms)との差が生まれた理由は、前回のC++実装がスレッド数を指定していなかったためで、OpenBLASの自動検出が最適でなかった可能性がある。

ポイント: openblas_set_num_threads() を明示すると再現性が上がり、WSL2では4スレッドが現状最速。


アプローチ 2:Eigen の BLAS バックエンド(EIGEN_USE_BLAS

動機

前回、EigenはOpenBLASより約2.3倍遅かった(476ms vs 206ms)。
EIGEN_USE_BLAS を定義すると、EigenのGEMM計算を外部BLASに委譲できる。
「Eigenの使いやすいAPIを保ちつつ、OpenBLASの速度を得られるか?」を検証した。

// cblas.h の前に定義する
#define EIGEN_USE_BLAS
#include <x86_64-linux-gnu/cblas.h>
#include <Eigen/Dense>

// 以降は通常の Eigen コード
Eigen::MatrixXd C = A * B;  // 内部で cblas_dgemm が呼ばれる

CMakeLists.txt での設定:

add_executable(bench_eigen_blas src/matmul_eigen_blas.cpp)
target_include_directories(bench_eigen_blas PRIVATE ${CBLAS_INCLUDE_DIR})
target_link_libraries(bench_eigen_blas PRIVATE Eigen3::Eigen ${OPENBLAS_LIB})

結果

実装 N=512 N=1024 N=2048
Eigen(純粋) 9.4 ms 59.1 ms 475.6 ms
Eigen + BLAS 4.4 ms 23.3 ms 229.8 ms
OpenBLAS直接(t4) 1.9 ms 28.0 ms 170.9 ms

考察

EIGEN_USE_BLAS でEigenは約2倍速くなったが、OpenBLAS直接呼び出しには届かなかった(229ms vs 171ms)。
理由として考えられるのは:

  • Eigen が内部でスレッド数を制御せず、デフォルト設定のまま動く
  • 行列配置(列優先 vs 行優先)の変換コスト

ポイント: EIGEN_USE_BLAS は純粋Eigenの倍速だが、直接cblas呼び出しの代替にはならない。「Eigenで書いてBLASで動かす」用途に限定すべき。


アプローチ 3:float32 SGEMM(精度を落として速度を得る)

動機

AVX2 は 256bit幅のSIMDレジスタを持つ。

  • double(64bit): 1レジスタに 4要素
  • float (32bit): 1レジスタに 8要素 ← 2倍!

理論上、cblas_sgemm(単精度)は cblas_dgemm(倍精度)の 2倍のスループット を発揮できる。
精度が落ちるというトレードオフがあるが、機械学習推論や物理シミュレーションではfloat32で十分な場合が多い。

cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
            N, N, N,
            1.0f, A.data(), N,   // float* 
                  B.data(), N,
            0.0f, C.data(), N);

結果

実装 N=512 N=1024 N=2048
OpenBLAS DGEMM(t4) 1.9 ms 28.0 ms 170.9 ms
OpenBLAS SGEMM 3.3 ms 12.4 ms 104.8 ms

考察

N=2048 で 104.8ms。DGEMM比で 約1.97倍速。ほぼ理論値の2倍を達成。
N=512ではSGEMMが若干遅い(3.3ms vs 1.9ms)。小行列ではSIMD効率よりメモリ帯域・起動コストが支配的になるためと考えられる。

ポイント: 精度を float32 に落とせる用途なら SGEMM で約2倍の高速化が可能。機械学習・グラフィクス・科学技術計算の多くはfloat32で十分。


総合比較(N=2048)

実装 N=2048 (ms) 対DGEMM基準
Eigen 純粋 475.6 0.43x
OpenBLAS DGEMM(1スレッド) 386.1 0.53x
OpenBLAS DGEMM(2スレッド) 229.2 0.90x
Eigen + BLAS backend 229.8 0.90x
OpenBLAS DGEMM(従来C++) 206.5 基準
OpenBLAS DGEMM(4スレッド明示) 170.9 1.21x
🏆 OpenBLAS SGEMM(float32) 104.8 1.97x

まとめ

「BLASより速くできるか?」への回答:

アプローチ 効果 推奨度
スレッド数チューニング 1.21x 速化 ⭐⭐⭐ 常に試す価値あり
Eigen + BLAS backend Eigen比 2x、BLAS直接比 0.9x ⭐⭐ Eigenの利便性を保つ用途向け
SGEMM(float32) 1.97x 速化 ⭐⭐⭐ 精度許容できるなら最有力

最も効果的な答えは「float32 SGEMM」
AMDのAVX2実装がSIMD幅を余すことなく使い切り、理論値に近い2倍を達成した。

次の選択肢として以下が考えられる:

  • AOCL(AMD Optimizing CPU Libraries):AMD公式のBLIS実装でZen向けに最適化されたCPUライブラリ。WSL2でも動作するが、AMD公式サイトでのアカウント登録・EULA同意が必要なためコンテナ環境では自動インストールが困難。ホスト環境であれば .deb を手動インストールして計測できる。
  • ROCm / rocBLAS(GPU):WSL2からAMD iGPU(Radeon Vega)へのROCmアクセスは非対応のため今回は断念。ホスト環境かつ専用GPU環境であれば有効な選択肢。

コード

src/matmul_openblas_mt.cpp, src/matmul_eigen_blas.cpp, src/matmul_sgemm.cpp を参照)

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?