スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Ubuntu + NVIDIA CUDA Toolkit 4.1 上でのメモリオブジェクトの確保

私の環境は、ハードウェア的にはホストメモリ3.2GB、GPUメモリ1GBである。この環境ではたしてメモリオブジェクトをどれだけ使用できるものか。

APIとしては、clGetDeviceInfo()の引数に、CL_DEVICE_MAX_MEM_ALLOC_SIZEを指定して問い合わせを行うことでチェックできる。OpenCLの仕様によると、最低でも128MBか、あるいはGPUメモリサイズの1/4のどちらか大きい方の値ということである。ただしGPUメモリサイズというのは、正確には、clGetDeviceInfo()の引数にCL_DEVICE_GLOBAL_MEM_SIZEを指定して得られる値のことで。若干端数がハードウェア構成上の値と違う可能性はある。私の環境の場合、この値は1023MBであった。そしてCL_DEVICE_MAX_MEM_ALLOC_SIZEの返り値は255MB。

では255MBを越えるメモリオブジェクトはまったく確保できないのかというと、実際に試してみると必ずしもそうとは限らないようである。

以下のようなテストプログラムを実行してみた。



#include "myCLManager2.h"
#include "myCLUtils.h"
#include <iostream>
#include <string>
#include <sstream>
#include <values.h>

string sizeStr(size_t size)
{
size_t rsize;
const char *unit;
if(size >= 1024 * 1024 * 1024){
rsize = size / (1024 * 1024 * 1024);
unit = "Gbytes";
}else if(size >= 1024 * 1024){
rsize = size / (1024 * 1024);
unit = "Mbytes";
}else if(size >= 1024){
rsize = size / 1024;
unit = "Kbytes";
}else{
rsize = size;
unit = "bytes";
}
stringstream s;
s << rsize << " " << unit;
return s.str();
}

int main(int argc, char **argv)
{
myCLManager2 clm;
cl_mem mobj;
char *buf;
size_t size;
for(size = 256; size <= LONG_MAX; size<<=1 ){
buf = new char[size];
for(size_t i = 0; i < size; i++){
buf[i] = i % 100;
}
MYCLCREATE(mobj,
clCreateBuffer,
clm.context,
CL_MEM_READ_WRITE,
size * sizeof(char),
NULL);
clFlush(clm.queues[0]);
MYCLCHECK(clEnqueueWriteBuffer,
clm.queues[0],
mobj,
CL_TRUE,
0,
size * sizeof(char),
buf,
0, NULL, NULL);
clFlush(clm.queues[0]);
for(size_t i = 0; i < size; i++){
buf[i] = 0;
}
MYCLCHECK(clEnqueueReadBuffer,
clm.queues[0],
mobj,
CL_TRUE,
0,
size * sizeof(char),
buf,
0, NULL, NULL);
for(size_t i = 0; i < size; i++){
if(buf[i] != i % 100){
std::cout << "buffer contents don't match for"
<< sizeStr(size) << ".\n";
}
}
clFlush(clm.queues[0]);
std::cout << "mobj allocation of " << sizeStr(size) << " succeeded.\n";
MYCLCHECK(clReleaseMemObject, mobj);
delete[] buf;
}
return 0;
}

やっていることは極めて単純である。myCLManager2は自分で作成した、OpenCLのコンテクストやキュー、プログラムオブジェクトの管理を行うヘルパークラスであるが、本質的ではない。単に普通にコンテクスト、キューの生成を行っていると思っていただければいい。

MYCLCHECK、MYCLCREATEも以前のエントリに書いたが、単にエラー処理を組み込んだマクロである。OpenCLのAPIが正常終了しなかったときはexit()するようになっている。

流れとしては、サイズを倍々にしながら、
そのサイズ分のホストメモリを確保
適当な内容で初期化
同じサイズでメモリオブジェクトを作成
clEnqueueWriteBufferでホストメモリからメモリオブジェクトに書き込み
ホストメモリの内容をクリア
メモリオブジェクトから先ほど書き込んだ内容をホストメモリに読み出し
最初の内容と一致するかチェック

ということを繰り返している。もし自分の環境で似たようなことをやりたい人がいたら、メモリを食いつぶしてシステムに影響が出ないとも限らないので、先に重要なファイルはセーブするなり何なりした上で十分心してやってもらいたい。

でまあ、これをとりあえず実行してみるとこんなになった。

mobj allocation of 256 bytes succeeded.
mobj allocation of 512 bytes succeeded.
mobj allocation of 1 Kbytes succeeded.
mobj allocation of 2 Kbytes succeeded.
(途中略)
mobj allocation of 128 Mbytes succeeded.
mobj allocation of 256 Mbytes succeeded.
mobj allocation of 512 Mbytes succeeded.
test7.cpp: 55 in main(): clEnqueueWriteBuffer failed due to CL_MEM_OBJECT_ALLOCATION_FAILURE

というわけで、512MBまでは実際にメモリオブジェクトを確保、書き込み、読み出しを問題なく行うことができた。あくまで前述の255MBという値は、最低限保証されている値というわけである。この後もう少し細かくテストしてみるとちょっと思いがけないことも分かったのだが、それは別エントリに後で書こう。


追記:
遅ればせながらプログラムソースを見やすくするためにSyntaxHighlighterを導入させていただいた。導入にあたっては、Linux愛好者の独り言 fc2ブログでソースコードを綺麗に表示する。(SyntaxHighLighter 3.0)を参考にさせていただいた。ありがとうありがとう。
スポンサーサイト

コメントの投稿

非公開コメント

管理人のみ閲覧できます

このコメントは管理人のみ閲覧できます
プロフィール

GM3D

Author:GM3D
FC2ブログへようこそ!

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
FC2カウンター
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。