FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://sites.google.com/site/fpgadevelopindex/

ZedBoard で Coremark

Coremark は EEMBC で配布されている、無料のCPU性能測定ベンチマークだ。 複数のアプリケーションセットで構成されており、ITERATION回数を指定して特定秒数の間に何回イタレーションを回せるかで性能が決定される。 また、クロック周波数に依存した値だけでなく、クロック周波数で割って、1サイクルあたりの性能を出すCMK/MHz も一般的に使われている。

ちなみにCoremarkの詳細はオフィシャルホームページを参照のこと。

http://www.eembc.org/techlit/coremark-whitepaper.pdf

ちなみに代表的なプロセッサのCoremark/MHzの値。

組み込み向けではルネサスのRXが意味分かんないくらい突出している。3.0を越えれば良いくらいの感じかな。 ちなみにPrescottを載せたのは、高いCPUは必ずしも高いサイクル性能を出せている訳ではないということ。周波数で稼いで、パイプライン長くしてるんだからしょうがないよね。

というわけで、Cortex-A9が乗っているZedBoardでCoremarkを動作させた。 EEMBCのホームページからCoremarkをダウンロードし、SDKにプロジェクトを作る。 移植用のファイル core_portme.c と core_portme.h を変更する。特に必要なのはサイクルを測定する部分。これにはZynqのタイマーを利用する。 このあたりのテクニックは、

Zynq design from scratch. Part 15. « New Horizons Zynq Blog

をめちゃくちゃ参考にさせてもらった。すごいやこの人。

ee_u32 GetTimerValue(ee_u32 TimerIntrId,ee_u16 Mode)

{

    int                 Status;
    XScuTimer_Config    *ConfigPtr;
    volatile ee_u32     CntValue  = 0;
    XScuTimer           *TimerInstancePtr = &Timer;

    if (Mode == 0) {
      // Initialize the Private Timer so that it is ready to use
      ConfigPtr = XScuTimer_LookupConfig(TimerIntrId);
      Status = XScuTimer_CfgInitialize (TimerInstancePtr, ConfigPtr,
              ConfigPtr->BaseAddr);
      if (Status != XST_SUCCESS) {
          print ("XST_FAILURE\n");
          return XST_FAILURE;
      }

      // Load the timer prescaler register.
      XScuTimer_SetPrescaler (TimerInstancePtr, TIMER_RES_DIVIDER);
      // Load the timer counter register.
      XScuTimer_LoadTimer (TimerInstancePtr, TIMER_LOAD_VALUE);
      // Start the timer counter and read start value
      XScuTimer_Start(TimerInstancePtr);
      CntValue = XScuTimer_GetCounterValue (TimerInstancePtr);
    } else {
       //  Read stop value and stop the timer counter
       CntValue = XScuTimer_GetCounterValue (TimerInstancePtr);
       XScuTimer_Stop(TimerInstancePtr);
    }

    return CntValue;
}

最初HAS_TIME_Hディレクティブを有効にしていて全然時間が合わなかったが、修正すると何とかあった。 SAMPLE_TIME_IMPLEMENTATIONを1にして、start_time()、stop_time()とかを編集する。 オリジナルのもとの酷似させたまま編集したので、↑の参考ページのものと比べると多少diffが取りやすいかもしれない。これはそのうちgithubに上げる。

コンパイル時にはディレクティブもいろいろ設定が必要。

f:id:msyksphinz:20150204022345j:plain

実行結果:

2K performance run parameters for coremark.
CoreMark Size    : 666
Total ticks      : 209493933
Total time (secs): 25.126709
Iterations/Sec   : 1989.914429
Iterations       : 50000
Compiler version : GCC4.8.3 20140320 (prerelease)
Compiler flags   : -O3
Memory location  : Please put data memory location here
            (e.g. code in flash, data on heap etc)
seedcrc          : 0xe9f5
[0]crclist       : 0xe714
[0]crcmatrix     : 0x1fd7
[0]crcstate      : 0x8e3a
[0]crcfinal      : 0xa14c
Correct operation validated. See readme.txt for run and reporting rules.
CoreMark 1.0 : 1989.914429 / GCC4.8.3 20140320 (prerelease) -O3 / Stack

1989 / 666(MHz) をすると2.98 なので、概ね公称値が出せている。