刹那(せつな)の瞬き

Willkömmen! Ich heiße Setsuna. Haben Sie etwas Zeit für mich?

B450とRyzen 7 5700Xとメモリの妙な話

B450 マザーボードRyzen 7 5700X を載せた PC での話です。
手持ちのメモリは DDR4-3600 なのですが、3200MHz で動作させています。

CPU AMD Ryzen 7 5700X (Zen3)
M/B GIGABYTE B450 AORUS PRO WIFI (BIOS: F65 / AMD AGESA V2 1.2.0.B)
GPU NVIDIA GeForce GTX 1050 Ti
Mem G.Skill F4-3600C19D-16GSXWB (CL19-20-20-40) 8GB x 2 枚
A: DDR4_2, B: DDR4_1 に装着し、Dual Channel で動作
AMD CPU では CL20 。定格に合わせて 3200MHz 1.200V 駆動


さて、この PC の Linux 環境でビルド時間が 1 分を超えるプロジェクトがあります。

このプロジェクトでは 850 個以上のオブジェクトファイルが生成されます。
なので、ビルド時間が長いのは仕方ないです。

ですが、手持ちのメモリモジュールは OC メモリだけど DDR4-3600 です。
現在の動作クロックは 3200MHz ですが、3600MHz 運用を試したくなりました。

これで少しでもビルド時間を短縮できれば嬉しい限りです。

3200MHz の方が 3600MHz よりビルド時間が短い

そんな事を期待しつつ、3200MHz と 3600MHz でビルド時間を比較したところ、

■ 3200MHz (CL20-20-20-40) 1.20V 動作時
ninja  996.76s user 51.36s system 1359% cpu 1:17.10 total
ninja  1000.24s user 51.15s system 1379% cpu 1:16.22 total
ninja  994.60s user 51.09s system 1354% cpu 1:17.20 total
■ 3600MHz (CL20-20-20-40) 1.35V 動作時
ninja  1029.85s user 52.66s system 1358% cpu 1:19.70 total
ninja  1030.50s user 52.56s system 1383% cpu 1:18.30 total
ninja  1029.95s user 52.79s system 1385% cpu 1:18.15 total

残念ながら期待した結果ではありません。

想定とは逆に 3200MHz 動作の方が数秒短い時間で完了しています。
しかも同じレイテンシ (CL20) なのにです。

メモリクロックを上げると同一時間内でのデータ転送量が増えるのに

私の想定では、メモリクロックを上げるとメモリ帯域幅が広くなり、結果として全体性能が向上するはずでした。

判断基準が崩れたので、まずはメモリ帯域幅を調査してみます。
Linux では STREAM でメモリ帯域幅を計測できるそうです。

(1) STREAM をビルド

公式サイトの "Source Code Directory" からソースコードを入手するのが正規ルートとは思いますが、私は GitHub から入手しました。

$ mkdir temp
$ cd temp
$ git clone https://github.com/jeffhammond/STREAM.git
$ cd STREAM
$ gcc -O2 -fopenmp stream.c -o stream_openmp

カレントディレクトリにstream_openmpが生成されます。

(2) STREAM の設定と実行

スレッド数を 96 に設定してからコマンドを実行します。

$ export OMP_NUM_THREADS=96
$ ./stream_openmp
(3) 実行結果

・3200MHz 動作

-------------------------------------------------------------
STREAM version $Revision: 5.10 $
-------------------------------------------------------------
This system uses 8 bytes per array element.
-------------------------------------------------------------
Array size = 10000000 (elements), Offset = 0 (elements)
Memory per array = 76.3 MiB (= 0.1 GiB).
Total memory required = 228.9 MiB (= 0.2 GiB).
Each kernel will be executed 10 times.
 The *best* time for each kernel (excluding the first iteration)
 will be used to compute the reported bandwidth.
-------------------------------------------------------------
Number of Threads requested = 96
Number of Threads counted = 96
-------------------------------------------------------------
Your clock granularity/precision appears to be 1 microseconds.
Each test below will take on the order of 8125 microseconds.
   (= 8125 clock ticks)
Increase the size of the arrays if this shows that
you are not getting at least 20 clock ticks per test.
-------------------------------------------------------------
WARNING -- The above is only a rough guideline.
For best results, please be sure you know the
precision of your system timer.
-------------------------------------------------------------
Function    Best Rate MB/s  Avg time     Min time     Max time
Copy:           16474.5     0.009888     0.009712     0.010094
Scale:          14672.5     0.011006     0.010905     0.011305
Add:            17845.3     0.013601     0.013449     0.013752
Triad:          16950.4     0.014359     0.014159     0.015236
-------------------------------------------------------------
Solution Validates: avg error less than 1.000000e-13 on all three arrays
-------------------------------------------------------------

・3600MHz 動作

-------------------------------------------------------------
STREAM version $Revision: 5.10 $
-------------------------------------------------------------
This system uses 8 bytes per array element.
-------------------------------------------------------------
Array size = 10000000 (elements), Offset = 0 (elements)
Memory per array = 76.3 MiB (= 0.1 GiB).
Total memory required = 228.9 MiB (= 0.2 GiB).
Each kernel will be executed 10 times.
 The *best* time for each kernel (excluding the first iteration)
 will be used to compute the reported bandwidth.
-------------------------------------------------------------
Number of Threads requested = 96
Number of Threads counted = 96
-------------------------------------------------------------
Your clock granularity/precision appears to be 1 microseconds.
Each test below will take on the order of 7064 microseconds.
   (= 7064 clock ticks)
Increase the size of the arrays if this shows that
you are not getting at least 20 clock ticks per test.
-------------------------------------------------------------
WARNING -- The above is only a rough guideline.
For best results, please be sure you know the
precision of your system timer.
-------------------------------------------------------------
Function    Best Rate MB/s  Avg time     Min time     Max time
Copy:           18774.9     0.008623     0.008522     0.008733
Scale:          16792.7     0.009668     0.009528     0.009716
Add:            19619.0     0.012304     0.012233     0.012494
Triad:          18706.5     0.012943     0.012830     0.013301
-------------------------------------------------------------
Solution Validates: avg error less than 1.000000e-13 on all three arrays
-------------------------------------------------------------

STREAM の実行結果から 3600MHz の方がメモリ帯域幅が広い事が確認できます。

これは期待通りの結果です。
実行する度に結果は変動しますが、傾向は同じでした。

他のベンチマークで計測してみる

メモリ帯域幅が広いのにビルド時間が遅くなる理由がわかりません。

そこで Linux でシステム全体のベンチマークを計測できるものを探したところ、PassMark Software 製のPerformanceTest Linuxを見つけました。

後述する内容は Ubuntu 24.04.1 LTS で実行した結果です。

(1) PerformanceTest Linux を取得・展開・実行

サイトから PerformanceTest Linux x86 64-bit をダウンロードして展開します。

$ wget https://www.passmark.com/downloads/PerformanceTest_Linux_x86-64.zip
$ unzip ./PerformanceTest_Linux_x86-64.zip 
Archive:  ./PerformanceTest_Linux_x86-64.zip
   creating: PerformanceTest/
  inflating: PerformanceTest/readme.txt  
  inflating: PerformanceTest/pt_linux_x64

展開後はpt_linux_x64を実行するだけですが、私の環境では共有ライブラリが不足しているのでエラーが発生します。

$ ./PerformanceTest/pt_linux_x64 
./PerformanceTest/pt_linux_x64: error while loading shared libraries: libncurses.so.5: cannot open shared object file: No such file or directory

Ubuntu 24.04.1 LTS では ncurses 系のバージョンは 6.4 で既にインストール済みです。
このままでは実行できないので、対象バージョンの共有ライブラリを手動で処理します。

$ wget http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2_amd64.deb
$ sudo dpkg -i libtinfo5_6.3-2_amd64.deb
$ wget http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2_amd64.deb
$ sudo dpkg -i libncurses5_6.3-2_amd64.deb

共有ライブラリの依存関係により、libtinfo5, libncurses5 の順にインストールします。
/usr/lib/x86_64-linux-gnu/ にそれぞれ lib*.so.5.9 なライブラリが存在するはずです。

(2) 実行結果

・3200MHz 動作

                   PassMark PerformanceTest Linux (11.0.1002)


AMD Ryzen 7 5700X 8-Core Processor (x86_64)
8 cores @ 4661 MHz  |  15.5 GiB RAM
Number of Processes: 16  |  Test Iterations: 1  |  Test Duration: Medium
--------------------------------------------------------------------------------
CPU Mark:                          26223
  Integer Math                     94430 Million Operations/s
  Floating Point Math              51557 Million Operations/s
  Prime Numbers                    108 Million Primes/s
  Sorting                          34499 Thousand Strings/s
  Encryption                       22772 MB/s
  Compression                      321855 KB/s
  CPU Single Threaded              3435 Million Operations/s
  Physics                          1206 Frames/s
  Extended Instructions (SSE)      17835 Million Matrices/s

Memory Mark:                       3252
  Database Operations              7185 Thousand Operations/s
  Memory Read Cached               35227 MB/s
  Memory Read Uncached             24495 MB/s
  Memory Write                     15995 MB/s
  Available RAM                    13484 Megabytes
  Memory Latency                   45 Nanoseconds
  Memory Threaded                  43501 MB/s
--------------------------------------------------------------------------------

Results not submitted
Upload results to cpubenchmark.net? [Y/n]:

Use ESC or CTRL-C to exit
A: Run All Tests   C: Run CPU Tests   M: Run Memory Tests   U: Upload Test Resul

・3600MHz 動作

                   PassMark PerformanceTest Linux (11.0.1002)


AMD Ryzen 7 5700X 8-Core Processor (x86_64)
8 cores @ 4661 MHz  |  15.5 GiB RAM
Number of Processes: 16  |  Test Iterations: 1  |  Test Duration: Medium
--------------------------------------------------------------------------------
CPU Mark:                          26005
  Integer Math                     92589 Million Operations/s
  Floating Point Math              50726 Million Operations/s
  Prime Numbers                    116 Million Primes/s
  Sorting                          34921 Thousand Strings/s
  Encryption                       21970 MB/s
  Compression                      306954 KB/s
  CPU Single Threaded              3436 Million Operations/s
  Physics                          1303 Frames/s
  Extended Instructions (SSE)      17248 Million Matrices/s

Memory Mark:                       3451
  Database Operations              7666 Thousand Operations/s
  Memory Read Cached               35225 MB/s
  Memory Read Uncached             25905 MB/s
  Memory Write                     17867 MB/s
  Available RAM                    13493 Megabytes
  Memory Latency                   41 Nanoseconds
  Memory Threaded                  47419 MB/s
--------------------------------------------------------------------------------

Results not submitted
Upload results to cpubenchmark.net? [Y/n]:

Use ESC or CTRL-C to exit
A: Run All Tests   C: Run CPU Tests   M: Run Memory Tests   U: Upload Test Resul

実行結果によると、Memory Mark では 3600MHz の方が 3200MHz より高い数値ですが、CPU Mark では逆転してます。

何度実行しても傾向は変わりません。
僅かな差ですが CPU の処理性能が落ちてる事が確認できます。

結局、メモリ設定は 3200MHz に戻した

私の場合、Linux 環境でビルド時間を短縮できないなら本末転倒です。
いくらベンチマークテストで傾向を調べても、ビルドの実行結果がすべてです。

その後、ビルド時間を短縮できるように、BIOS 画面から

  • CPU Clock Control
  • CPU Clock Ratio
  • System Memory Multiplier
  • Standard Timing Control
  • Advanced Timing Control
  • DRAM Voltage

等の設定値を変更して、組み合わせを色々と試しましたが、結果は芳しくありません。
なので、3600MHz ではなく 3200MHz 設定に戻しました。

私の用途では当初の設定値が適切だったみたいです。
と言うか、数秒の差なので元の状態で妥協します。

根本的に何か間違った事をしてなければ良いのですが...

自分用メモ

・気になる点

  • FSB:DRAM は 1:16 (3200MHz), 3:54 (3600MHz) 
  • B450 の SATASSD/HDD を接続しているから?NVMeでは?
  • Zen3 世代の CPU なので X570, B550 チップセットでは?
  • もし APU だったら?
  • Windows では?

 等々

・現在の BIOS 設定

M.I.T.
Advanced Frequency Settings
CPU Clock Control Auto (既定値)
Host Clock Value の表示は 100.00MHz
CPU Ratio Mode All cores (既定値)
CPU Clock Ratio Auto (既定値)
CPU Frequency の表示は 3.40GHz
Advanced Frequency Settings - Advanced CPU Settings
SVM Mode Enabled
Advanced Memory Settings
Extream Memory Profile(X.M.P.) Profile1
DDR4-3600 19-20-20-40-60-1.35V
System Memory Multiplier 32.00
Memory Frequency(MHz) の表示は 3200MHz
Memory Timing Mode Auto (既定値)
Advanced Voltage Settings
Dynamic Vcore(DVID) Auto (既定値)
Dynamic VCORE SOC(DVID) Auto (既定値)
DRAM Voltage (CH A/B) 1.200V
BIOS
<UEFI> CSM Support Enabled (既定値)
Peripherals
AMD CPU fTPM Enabled (既定値)

 

・メモリの設定値

DDR4-3200 CL18-18-18-38-56-1T 1.2V 動作まで確認済み

暇ができたら DRAM Calculator for Ryzen 等を利用して、もう少し詰めてみる