はじめに
最近のCPUには例外なく命令キャッシュとデータキャッシュを持っています。
あまりにも一般的になりすぎて、キャッシュがどのくらい効果があるのか知らない人もいると思います。
先日投稿した Linuxでユーザー空間で動作するプログラムとハードウェアがメモリを共有するためのデバイスドライバ で紹介した udmabufを使えば、バッファのメモリ空間のデータキャッシュの設定を変更することが出来ます。
この機能を使って、データキャッシュがどのくらい効果があるか測定しました。
測定環境
- ハードウェア : ZYBO Zynq-7000
- CPU : ARM Cortex-A9
- レベル1 キャッシュ : 32KB 4ウェイセットアソシエイティブ
- レベル2 キャッシュ : 512KB 8ウェイセットアソシエイティブ
- 外部メモリ : DDR3 512MB x32 1050Mbps
- 動作周波数 : 650MHz
- OS : Linux Kernel Version 3.8
データキャッシュの設定
udmabuf で出来るデータキャッシュの設定は次の4通り。詳細は udmabuf の説明を参照してください。
-
データキャッシュあり
-
データキャッシュなし + ライトコンバインなし
-
データキャッシュなし + ライトコンバインあり
-
DMAコヒーレンシモード
ただし、最後のDMAコヒーレンシモードに関しては未だ詳細は不明です。今回の測定では除外します。
ライトコンバインは、連続したアドレスに連続して書き込む場合、それらの書き込みをまとめて行います。
測定用のプログラム
次のようなプログラムを走らせて処理時間を計測しました。
udmabuf_test.c
int check_buf(unsigned char* buf, unsigned int size)
{
int m = 256;
int n = 10;
int i, k;
int error_count = 0;
while(--n > 0) {
for(i = 0; i < size; i = i + m) {
m = (i+256 < size) ? 256 : (size-i);
for(k = 0; k < m; k++) {
buf[i+k] = (k & 0xFF);
}
for(k = 0; k < m; k++) {
if (buf[i+k] != (k & 0xFF)) {
error_count++;
}
}
}
}
return error_count;
}
int clear_buf(unsigned char* buf, unsigned int size)
{
int n = 100;
int error_count = 0;
while(--n > 0) {
memset((void*)buf, 0, size);
}
return error_count;
}
測定結果
プログラム | データ キャッシュ |
ライト コンバイン |
DMAバッファのサイズ | ||
1MByte | 5MByte | 10MByte | |||
check_buf | 有効 | - | 0.437[sec] | 2.171[sec] | 4.375[sec] |
無効 | 無 | 2.283[sec] | 11.414[sec] | 22.830[sec] | |
有 | 1.655[sec] | 8.391[sec] | 16.587[sec] | ||
clear_buf | 有効 | - | 0.067[sec] | 0.362[sec] | 0.717[sec] |
無効 | 無 | 0.914[sec] | 4.563[sec] | 9.128[sec] | |
有 | 0.062[sec] | 0.310[sec] | 0.621[sec] |