OpenCLのマンデルブロ集合

ホストプログラム
[cpp]
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<CL/cl.h>
#include<string>

#define MAX_SOURCE_SIZE (0x100000)
#define MEM_SIZE (1000)

using namespace std;

int main()
{
//char string[MEM_SIZE];

FILE *fp;
char fileName[] = "./calc.cl";
char *source_str;
size_t source_size;

fp = fopen(fileName, "r");
if(!fp)
{
cout << "file failed" <<endl;
exit(1);
}
source_str = (char *)malloc(MAX_SOURCE_SIZE);
source_size = fread(source_str,1,MAX_SOURCE_SIZE,fp);
fclose(fp);

cl_int status;
cl_platform_id platforms[2];
cl_uint num_platforms;
status = clGetPlatformIDs(2, platforms, &num_platforms);
//cout << status << endl;

cl_device_id devices;
cl_uint num_devices;
cl_context context;
status = clGetDeviceIDs(platforms[1], CL_DEVICE_TYPE_GPU, 4, &devices, &num_devices);
//cout << status << endl;

context = clCreateContext(NULL, 4, &devices, NULL, NULL, &status);
//cout << status << endl;

cl_command_queue queue;
queue = clCreateCommandQueue(context, devices, 0, &status);
//cout <<"queue:"<<status << endl;

cl_program program;
program = clCreateProgramWithSource(context, 1, (const char**)&source_str, &source_size, &status);
//cout << status << endl;

status = clBuildProgram(program, num_devices, &devices, NULL, NULL, NULL);
//cout << status << endl;

/*////////////////////////

size_t logsize;
status = clGetProgramBuildInfo(program,devices,CL_PROGRAM_BUILD_LOG,0,NULL,&logsize);
if(status == CL_SUCCESS)
{
char *logbuffer;
logbuffer = new char[logsize + 1];
if(logbuffer == NULL)
{
cout << "memory allocation failed."<<endl;
//return;
}

status = clGetProgramBuildInfo(program,devices,CL_PROGRAM_BUILD_LOG,logsize,logbuffer,NULL);
if(status == CL_SUCCESS)
{
logbuffer[logsize]=’\0’;
cout << "build log" << endl;
cout << logbuffer << endl;
}
delete [] logbuffer;
}

*////////////////////////

cl_kernel kernel;
kernel = clCreateKernel(program, "calc", &status);
//cout << status << endl;

float Outx[MEM_SIZE];
float Outy[MEM_SIZE];
bool OutCheck[MEM_SIZE][MEM_SIZE];
Outx[0] = -2;
Outy[0] = -2;
for(int i= 0; i < MEM_SIZE-1 ;i++)
{
Outx[i+1] = Outx[i] + (4.0 / MEM_SIZE);
Outy[i+1] = Outy[i] + (4.0 / MEM_SIZE);

for(int j = 0; j < MEM_SIZE ;j++)
{
OutCheck[i][j] = 0;
}
}

cl_mem memoutx, memouty, memoutcheck;
memoutx = clCreateBuffer(context, CL_MEM_READ_WRITE, MEM_SIZE * sizeof(float), NULL, &status);
//cout <<status<<endl;
memouty = clCreateBuffer(context, CL_MEM_READ_WRITE, MEM_SIZE * sizeof(float), NULL, &status);
//cout <<status<<endl;
memoutcheck = clCreateBuffer(context, CL_MEM_READ_WRITE, MEM_SIZE * MEM_SIZE * sizeof(bool), NULL, &status);
//cout <<status<<endl;

status = clEnqueueWriteBuffer( queue, memoutx, CL_TRUE, 0, MEM_SIZE * sizeof( float ), Outx, 0, NULL, NULL );
//cout << status << endl;
status = clEnqueueWriteBuffer( queue, memouty, CL_TRUE, 0, MEM_SIZE * sizeof( float ), Outy, 0, NULL, NULL );
//cout << status << endl;
status = clEnqueueWriteBuffer( queue, memoutcheck, CL_TRUE, 0, MEM_SIZE * MEM_SIZE * sizeof( bool ), OutCheck, 0, NULL, NULL );
//cout << status << endl;

status = clSetKernelArg(kernel, 0,sizeof(cl_mem),(void *)&memoutx);
status = clSetKernelArg(kernel, 1,sizeof(cl_mem),(void *)&memouty);
status = clSetKernelArg(kernel, 2,sizeof(cl_mem),(void *)&memoutcheck);
//cout <<"カーネルに渡す引数セット:"<<status<<endl;

//status = clEnqueueTask(queue, kernel, 0, NULL, NULL);
size_t global_work_size[] = {MEM_SIZE * MEM_SIZE};
size_t local_work_size[] = {MEM_SIZE};
status = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global_work_size, local_work_size, 0, NULL, NULL);
if( status < 0){
cout <<"実行:"<<status<<endl;
cout << CL_DEVICE_MAX_WORK_GROUP_SIZE << endl;
exit(0);
}

//status = clEnqueueReadBuffer(queue, memoutx, CL_TRUE, 0, MEM_SIZE * sizeof(float), Out, 0, NULL, NULL);
//status = clEnqueueReadBuffer(queue, memouty, CL_TRUE, 0, MEM_SIZE * sizeof(float), Out, 0, NULL, NULL);
status = clEnqueueReadBuffer(queue, memoutcheck, CL_TRUE, 0, MEM_SIZE * MEM_SIZE * sizeof(bool), OutCheck, 0, NULL, NULL);
//cout <<"結果取り出し:"<<status<<endl;

for(int i = 0;i < MEM_SIZE; i++)
{
for(int j = 0;j < MEM_SIZE; j++)
{
if(OutCheck[i][j] == 0){
cout << Outx[i]<< " " << Outy[j] << endl;
}
}
}

clReleaseMemObject(memoutx);
clReleaseMemObject(memouty);
clReleaseMemObject(memoutcheck);
clReleaseKernel(kernel);
clReleaseProgram(program);
clReleaseCommandQueue(queue);
clReleaseContext(context);
}
[/cpp]

カーネルプログラム
[cpp]
#define MEM_SIZE (1000)
__kernel void
calc(__global float *outx,
__global float *outy,
__global bool outcheck[MEM_SIZE][MEM_SIZE] )
{

#define MaxCalcNum 100

int width = 2, height = 2, j = 0;
int out[MEM_SIZE*MEM_SIZE];

#pragma OPENCL EXTENSION cl_khr_fp64:enable
//int index_x = get_global_id(0);
//int index_y = get_global_id(1);
int index_x = get_group_id(0);
int index_y = get_local_id(0);

if(index_x > MEM_SIZE)index_x = 1;
if(index_y > MEM_SIZE)index_y = 1;
double prevX = 0.0f;
double prevY = 0.0f;

for(int i = 0; i < MaxCalcNum ; i++)
{
double newX = (prevX * prevX) – (prevY * prevY) + outx[index_x];
double newY = 2.0f * prevX * prevY + outy[index_y];

if ((newX * newX) + (newY * newY) > 4.0f)
{
outcheck[index_x][index_y] = -1;
break;
}
else
{
prevX = newX;
prevY = newY;
}
}
}
[/cpp]

画像出力

$ g++ -o main_cp main_cp.cpp -lOpenCL
$ ./main_cp > mandel.txt
$ gnuplot
> set terminal png
> set out "mandel.png"
> plot "mandel.txt"

楽しむためにはリスクをとらなくちゃ

こんにちわ。
最近普通の日記を書いてないと思いつつも、特に書くこともなく研究室バイト遊びを繰り返している日々です。

こんなんでいいのかなーってぐらい最近色々うまく回っている気がするのですが、一抹の不安がある。
今の自分の行動がすべて自分の将来のための布石になっているかということ。
自分の描いた理想の未来に少しでも近づけているのか。歩み出すその一歩は他人に流されてやしないか。

物事には優先順位があって、その一番上に絶対にやらなくちゃいけないことがある。それが今は「大学を卒業すること」。そのためには卒論を書かなければいけないこと。
これは絶対にやらなければならないこと。

ただ裏を返すと、本当にやらなければならないことってそれしかない。それが必要最小限であり、それ以外のことは何もしなくていい。むしろ4回生になった今、他の余計なことはしないほうがいいかもしれないぐらい。

でもなんかこーいうのって一生続く不安かもしれない。おそらく社会人になっても、「毎日遅刻せず出社する」とかそーいう絶対にやらなくちゃいけないことっていうのはあるんだと思う。それはきっと自分が生きていくための必要条件なんだと思うんだけど、やっぱりそれだけじゃ現状維持のままになるんだろうなと思う。現状維持でもいいんだけど、もっとこう自分自身、自分の周りをより良くしていくことが楽しいんじゃないかと思うわけで、そのためにはある程度のリスクっていうものをとらなくちゃいけないって思った。

そりゃあ今自分にとって本当にやらなければならないことって「大学を卒業すること」ぐらいしかない。ならば、もう全部バイトもやめて夢とかも考えるのやめて、本当に卒業するためだけに動けばいい。授業だってちゃんと出て出席とって、夜は早く寝て、たまに研究室行ってダベって、それなりに楽しんで、でもその人間関係っていうのはそれなりにして、飲み会に参加するのも次の日のことを考えて金曜か土曜だけにして、家が大好きで家には7時に帰ってご飯食べつつドラマ見て12時には寝てっていうそんな普通のことをすればいいんだ。卒業するためだけに動けばいい。誰も文句も言わないし、反感も買うことはない。

でもそれって【本当に】楽しいのか?

おれはおれの人生しか歩んだことないし歩めないから、断定はできないけど、もう一度よく考えてみろよって思う。それで楽しいって言われたら何も言えねぇけど。。。
そんでよく考えた結果、それじゃ嫌だとか、なんかありきたりな毎日とか、本当は自分はこうなりたい!とか思うなら、

もっとリスク取れよ!!!って思う。
楽しいことするためには、リスクとらなくちゃって、金だけで買える娯楽なんて本当の楽しさじゃないって!
誰かに寄りかかってるうちは本当に楽しいことを知らないんじゃないかって思っちゃう。きっとその人が楽しいって思ってることっていうのも他の誰かが作った楽しさの一部でしかないんだろうなって思っちゃう。

うん、なんかそれが寂しいっていうかそれを分かってもらえないのが辛い。

もうなんかここまで勝手に自分の妄想だけで日記を書いている気分になってきたけど、なんかそんな風に思うことが多い。
久々の日記はここまで。

OpenCLの環境(プラットホーム、デバイス)表示

[cpp]
#include <CL/cl.h>
#include <iostream>

using namespace std;

int main(){

/*–Platform取得–*/
cl_platform_id id[3];//プラットホームID

cl_int num = 3;//プラットホームを3つまで見つける
cl_uint Rnum;//実際に取得したプラットホーム数
cl_char name[1024];//プラットホーム名

clGetPlatformIDs(num,id,&Rnum);
cout<<"Platform Max Number = "<<Rnum<<endl<<endl;

for(int i = 0;i < Rnum;i++)//プラットホームを探し、すべてのプラットホームを表示
{
clGetPlatformInfo(id[i],CL_PLATFORM_NAME,sizeof(name),name,NULL);
cout<<"Platform Name = "<<name<<endl;

/*–デバイス取得–*/
cl_device_id dev[10];//デバイスID(構造体のアドレスが格納される)

cl_uint DC;//実際に取得したデバイス数
cl_char buff[1024];//デバイス名
cl_int num1 = 10;
clGetDeviceIDs(id[i],CL_DEVICE_TYPE_ALL,num1,dev,&DC);//プラットホームID,デバイスタイプ,
cout<<"Device Max Number = "<<DC<<endl;

for(int j= 0;j < DC;j++)
{

clGetDeviceInfo(dev[j],CL_DEVICE_NAME,sizeof(buff),buff,NULL);
cout<<" Device Name = "<<buff<<endl;
}
cout << endl;
}
}
[/cpp]