現在地 >> メニュー >> OpenCL >> OpenCL編02 >> OpenCL編02::まとめ1

問題

100個の配列要素に値を設定し、GPUに転送。1000を加えてGPUから取り出して
結果が正しくできているかを確認せよ。

答え

gpuMain.cl

__kernel void gpuMain(__global int *Ary)
{
	unsigned int id = get_global_id(0);//配列の通し番号でID取得
	Ary[id] += 1000; 
}

main.cpp

#include <oclUtils.h>//OpenCL用ユーティティヘッダ
#include <fstream>
#include <iostream>

//OpenCL用グローバル変数
cl_context cxGPUContext;//OpenCLコンテキスト用
cl_kernel myclKernel; //OpenCLのカーネル用
cl_command_queue commandQueue;//コマンドキュー

const int aryNUM = 100;
int sampleData[aryNUM];

//------- メイン --------//
int main(int argc, const char** argv) 
{
	//初期設定
	for(int loop = 0; loop < aryNUM; ++loop)
	{
		sampleData[loop] = loop + 1;
		std::cout << sampleData[loop] << "\n";
	}
	std::cout << "Start!\n";
	cl_int ciErrNum = CL_SUCCESS; //エラーチェック用


	//--- プラットフォームIDの取得 ---//
	cl_platform_id cpPlatform = NULL;//プラットフォームID

	ciErrNum = oclGetPlatformID(&cpPlatform);
	if (ciErrNum != CL_SUCCESS)
	{
		std::cerr << "Can't Get PlatformID\n";
		shrEXIT(argc,argv);
	}


	//--- デバイスの取得 ---//
	cl_uint ciDeviceCount = 0; //デバイス数
	cl_device_id *cdDevices = NULL;//デバイスID
	
	//デバイス数取得 → デバイスID取得
	ciErrNum = clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 0, NULL, &ciDeviceCount);
	cdDevices = new cl_device_id[ciDeviceCount];
	ciErrNum = clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, ciDeviceCount, cdDevices, NULL);
	if (ciErrNum != CL_SUCCESS)
	{
		std::cerr << "Error @ Getting device Infomation\n";
		shrEXIT(argc,argv);
	}


	//コンテキストの作成
	cxGPUContext = clCreateContext(0, ciDeviceCount, cdDevices, NULL, NULL, &ciErrNum);
	if (ciErrNum != CL_SUCCESS)
	{
		std::cerr << "Can't Create OpenCL Context\n";
		shrEXIT(argc, argv);
	}


	//コマンドキューの作成
	commandQueue = clCreateCommandQueue(cxGPUContext, (*cdDevices), 0, &ciErrNum);
	if (ciErrNum != CL_SUCCESS)
	{
		std::cerr << " Error in clCreateCommandQueue call !!!\n";
		shrEXIT(argc, argv);
	}

	//GPUのソースコードを読み込む
	std::ifstream myclSource("gpuMain.cl");
	std::istreambuf_iterator<char> vdataBegin(myclSource);
	std::istreambuf_iterator<char> vdataEnd;
	std::string myclStr(vdataBegin,vdataEnd);
	const char *bfile = myclStr.c_str();
	const size_t program_length = myclStr.size();

	//プログラムを作成する
	cl_program cpProgram = clCreateProgramWithSource(cxGPUContext, 1, &bfile, &program_length, &ciErrNum);
	if (ciErrNum != CL_SUCCESS)
	{
		std::cerr << "Error: Failed to create program\n";
		shrEXIT(argc, argv);
	}

	//プログラムのビルド
	ciErrNum = clBuildProgram(cpProgram, 0, NULL, NULL, NULL, NULL);
	if (ciErrNum != CL_SUCCESS)
	{
		shrLogEx(LOGBOTH | ERRORMSG, ciErrNum, STDERROR);//ログの出力
		shrEXIT(argc, argv);
	}

	//カーネルの作成
	myclKernel = clCreateKernel(cpProgram, "gpuMain", &ciErrNum);
	if (ciErrNum != CL_SUCCESS)
	{
		shrLog("Error: Failed to create kernel\n");//ログの出力
		shrEXIT(argc, argv);
	}

	
	//---- ここからGPUの処理  ----//
	//デバイス上にメモリ確保
	cl_mem dviceAry = clCreateBuffer(cxGPUContext, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
                                sizeof(sampleData), &sampleData, NULL);

	/*cl_mem dviceAry = clCreateBuffer(cxGPUContext, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR,
		sizeof(sampleData), &sampleData, NULL);*/

	sampleData[99] = 900;//GPU側には反映されない

	//データをコピー
	clEnqueueWriteBuffer(commandQueue,dviceAry,CL_TRUE,0,sizeof(sampleData),sampleData,0,NULL,NULL);

	//カーネルに引数を設定する
	clSetKernelArg(myclKernel,0,sizeof(cl_mem), (void *) &dviceAry);


	//実行
	//CUDAとOpenCLの用語の対応
	//Thread == work-item
	//block == workgroup
	size_t WorkSize[1] = {aryNUM};//ワークサイズ
	clEnqueueNDRangeKernel(commandQueue, myclKernel, 1, NULL, WorkSize, NULL,0, NULL, NULL);

	//データを取り出し
	clEnqueueReadBuffer(commandQueue, dviceAry, CL_TRUE, 0,sizeof(sampleData), &sampleData, 0, NULL, NULL);


	//使い終わったらコンテキストなどの各種破棄
	clReleaseContext(cxGPUContext);
	clReleaseKernel(myclKernel);
	clReleaseProgram(cpProgram);
	clReleaseCommandQueue(commandQueue);
	clReleaseMemObject(dviceAry);
	delete [] cdDevices;

	std::cout << "-------------  after   --------------------------\n";
	for(int loop = 0; loop < aryNUM; ++loop)
	{
		std::cout << sampleData[loop] << "\n";
	}

	shrEXIT(argc, argv);//ログ等を出力して終了へ

	return 0;

}

目次

― その他 ―

Wiki内検索

計測中...(07.10.8〜)

Save The World






▲よろしければ広告のクリックもお願いします


▲ランキングに参加しました

管理人/副管理人のみ編集できます