DhrystoneでSTマイクロのベンチマークを取る
Dhrystone(ドライストーン)というプログラムでRaspberry Py Picoと、それとの比較のためにSTマイクロマイコンのベンチマークを取ってみたいと思います。
まずは慣れているSTマイクロマイコンでやってみます。開発環境はWindows10です。
Picoとの比較なのでCortex M0+であるSTM32G031マイコンなどを使いたいところですが持っていないので持っているNucleo-F411RE(STM32F411RE)でやってみます。
Dhrystoneプログラムはここ↓↓↓を使用させてもらいました。
開発ツールのSTM32CubeIDEでNucleo-F411REプロジェクトを新規作成します(とりあえずプロジェクト名はDhrystoneRunとしました)。
プロジェクトを新規作成するとシステムクロックは84MHzになっているので、これを100MHzにします。
できたプロジェクトにダウンロードしたファイルのうち「dhry_1.c」「dhry_2.c」「dhry.h」を開発ツール上の「inc」フォルダー、「Src」ファルダー上に直接drag & dropします。
dhry_1.cはメインモジュールでそこからdhry_2.cにあるサブモジュールを呼び出しています。
dhry_1.cのmain()をdhry_1()に変えて、そのdhry_1関数をmain()から呼び出すようにします。
96 97 98 99 |
/* USER CODE BEGIN 2 */ dhry_1(); /* 追加 */ /* USER COdE END 2 */ |
時間測定関係が動かないので、dhry.hの先頭に”#define TIME”を追加して既存の時間測定を無効にして、STマイクロの時間測定関数の”HAL_GetTick()”で時間測定をします。また”HAL_GetTick()”はmsec単位ですが、元々はusec単位なので、計算結果のMicrosecondsを1000で割り、Dhrystones_Per_Secondに1000を掛けておきます。
147 148 149 150 151 |
/* Compiler and system dependent definitions: */ #define TIME /* 追加 */ #ifndef TIME ... |
140 141 142 143 |
#ifdef TIME // Begin_Time = time ( (long *) 0); /* コメントアウト */ Begint_Time = HAL_GetTick(); /* 追加 */ #endif |
202 203 204 205 |
#ifdef TIME // End_Time = time ( (long *) 0); /* コメントアウト */ End_Time = HAL_GetTick(); /* 追加 */ #endif |
273 274 275 276 277 278 279 280 |
#ifdef TIME // Microseconds = (float) User_Time * Mic_secs_Per_Second // / (float) Number_Of_Runs; /* コメントアウト */ Microseconds = (float) User_Time / 1000 * Mic_secs_Per_Second / (float) Number_Of_Runs; /* 追加 */ // Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time; /* コメントアウト */ Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time * 1000; /* 追加 */ #else |
またprinf,scanfは動かないので、printfはともかくscanfで指定している繰り返し回数を1e6などに決め打ちします。
124 125 126 |
scanf ("%d", &n); // Number_Of_Runs = n; // コメントアウト Number_Of_Runs = 1e6; // 追加 |
1e6(=1,000,000回)、最適化最大で処理時間5秒位です。
Warningはいっぱい出ますが、これでとりあえず動きます。
あと最適化を最大(-O3)にしておきます。
「Project」→「Properties」→「C/C++ Build」→「Settings」→「MCM GCC Compiler」→「Optimization」→「Optimization level」を”Optiize most(-O3)”にします。
これで「Run」→「Debug(F11)」とすると、「Edit Configuration」ウィンドウが開くのでそのまま「OK」を押します(Edit Configurationウィンドウが開くのは最初の1回だけです)。
そうするとプログラムがbuild/ロードされて、main()関数の最初のところでbreakして止まっているのでそのまま「Run」→「Resume(F8)」してプログラムを走らせます。5秒くらいで終わるので(繰り返し回数が1,000,000回の場合)、「Run」→「Suspend」でプログラムを止めてmain()関数の”while (1)”のあたりで止まっていたら、「Expression」タブに”Microseconds”変数と”Dhrystones_Per_Second”変数を追加して値を読み取ってみます。
Dhrystones_Per_Secondの値を1757で割るとDMIPS値になるようなので1757で割ると
209161.266 / 1757 ≒ 119.0
になります。STM32F411のデータシートを見ると125DMIPSとなっているので大体あっていますね(当たり前か)。
このプロジェクトはGitHubにあります。
GitHubのプロジェクトはWarningが出ないようにしていて、更にprintf, scanfにも対応しています。このpritf, scanfを使うには、CubeIDE(Eclipse)にUart通信拡張を組み込むか、外部のTeratermを使う必要があります。
またWariningを出ないようにすると動作が軽くなるのか、これでベンチマークを取ってみると約126DMIPSでした。
次回はRaspberry Pi Picoのベンチマークを取っていきたいと思います。