質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

並列処理

複数の計算が同時に実行される手法

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

1回答

3249閲覧

OpenCLでの二次元配列の処理の仕方について

khsh

総合スコア8

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

並列処理

複数の計算が同時に実行される手法

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/01/10 16:52

編集2022/01/12 10:55

###前提・実現したいこと
OpenCLで+1するプログラムを作成してみました。
https://peta.okechan.net/blog/archives/2538
を参考にしています。

int index = get_global_id(0);
int index2 = get_global_id(1);

を用いて
data[index*M+index2] += 1.0;
のようにアクセスしたいと思っています。

###発生している問題・エラーメッセージ
int index = get_global_id(0);
int index2 = get_global_id(1);
を行うと常にindexとindex2に同じ値が格納されてしまいます。
ほとんどの部分が+1されず終わっています。

###該当のソースコード // // main3.cpp // #include <iostream> #include <vector> #include <OpenCL/opencl.h> #include <numeric> #define PLATFORM_MAX 4 #define DEVICE_MAX 4 void EC(cl_int result, const char *title) { if (result != CL_SUCCESS) { std::cout << "Error: " << title << "(" << result << ")\n"; } } cl_int err = CL_SUCCESS; void EC2(const char *title) { if (err != CL_SUCCESS) { std::cout << "Error: " << title << "(" << err << ")\n"; } err = CL_SUCCESS; } int main(int argc, const char * argv[]) { // プラットフォーム一覧を取得 cl_platform_id platforms[PLATFORM_MAX]; cl_uint platformCount; EC(clGetPlatformIDs(PLATFORM_MAX, platforms, &platformCount), "clGetPlatformIDs"); if (platformCount == 0) { std::cerr << "No platform.\n"; return EXIT_FAILURE; } // 見つかったプラットフォームの情報を印字 for (int i = 0; i < platformCount; i++) { char vendor[100] = {0}; char version[100] = {0}; EC(clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR, sizeof(vendor), vendor, nullptr), "clGetPlatformInfo"); EC(clGetPlatformInfo(platforms[i], CL_PLATFORM_VERSION, sizeof(version), version, nullptr), "clGetPlatformInfo"); std::cout << "Platform id: " << platforms[i] << ", Vendor: " << vendor << ", Version: " << version << "\n"; } // デバイス一覧を取得 cl_device_id devices[DEVICE_MAX]; cl_uint deviceCount; EC(clGetDeviceIDs(platforms[0], CL_DEVICE_TYPE_GPU, DEVICE_MAX, devices, &deviceCount), "clGetDeviceIDs"); if (deviceCount == 0) { std::cerr << "No device.\n"; return EXIT_FAILURE; } // 見つかったデバイスの情報を印字 std::cout << deviceCount << " device(s) found.\n"; for (int i = 0; i < deviceCount; i++) { char name[100] = {0}; size_t len; EC(clGetDeviceInfo(devices[i], CL_DEVICE_NAME, sizeof(name), name, &len), "clGetDeviceInfo"); std::cout << "Device id: " << i << ", Name: " << name << "\n"; } // コンテキストの作成 cl_context ctx = clCreateContext(nullptr, 1, devices, nullptr, nullptr, &err); EC2("clCreateContext"); // コンパイル済みclプログラムの読み込み const char* bitcode_path = "kernel2.cl.gpu_32.bc"; size_t len = strlen(bitcode_path); cl_program program = clCreateProgramWithBinary(ctx, 1, devices, &len, (const unsigned char**)&bitcode_path, nullptr, &err); EC2("clCreateProgramWithBinary"); // プログラムのビルド EC(clBuildProgram(program, 1, devices, nullptr, nullptr, nullptr), "clBuildProgram"); // カーネルの作成 cl_kernel kernel = clCreateKernel(program, "addone", &err); EC2("clCreateKernel"); // データを用意 int n = 10; std::vector<float> data(n*n,0.0f); // デバイスメモリを確保しつつデータをコピー cl_mem device_mem = clCreateBuffer(ctx, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(float) * n*n, data.data(), &err); EC2("clCreateBuffer"); // カーネルの引数をセット EC(clSetKernelArg(kernel, 0, sizeof(cl_mem), &device_mem), "clSetKernelArg"); EC(clSetKernelArg(kernel, 1, sizeof(int), &n), "clSetKernelArg"); // コマンドキューの作成 cl_command_queue q = clCreateCommandQueue(ctx, devices[0], 0, &err); EC2("clCreateCommandQueue"); // カーネルの実行 size_t global[2],local[2],offset[2]; offset[0] = 0; offset[0] = 0; global[0] = n; global[1] = n; local[0] = 1; local[1] = 1; EC(clEnqueueNDRangeKernel(q, kernel, 2, offset, global, NULL, 0, nullptr, nullptr), "clEnqueueNDRangeKernel"); // 結果を読み込み EC(clEnqueueReadBuffer(q, device_mem, CL_TRUE, 0, sizeof(float) * n*n, data.data(), 0, nullptr, nullptr), "clEnqueueReadBuffer"); // 結果の印字 for (int i = 0; i < n*n; i++) { std::cout << data[i] << ", "; } std::cout << "\n"; float total = std::accumulate(data.begin(),data.end(),0.0); std::cout << total << std::endl; // コマンドキューの解放 EC(clReleaseCommandQueue(q), "clReleaseCommandQueue"); // デバイスメモリを解放 EC(clReleaseMemObject(device_mem), "clReleaseMemObject"); // カーネルの解放 EC(clReleaseKernel(kernel), "clReleaseKernel"); // プログラムの解放 EC(clReleaseProgram(program), "clReleaseProgram"); // コンテキストの解放 EC(clReleaseContext(ctx), "clReleaseContext"); std::cout << "Done.\n"; return EXIT_SUCCESS; } //ここからカーネル部分 //kernel2.cl __kernel void addone(__global float* data,const int n) { int index = get_global_id(0); int index2 = get_global_id(1); int dim = get_work_dim(); printf("get_work_dim = %d\n",dim); printf("index = %d , index2 = %d \n",index,index2); data[index*n+index2] += 1.0f; } ```C++

###試したこと
EC(clEnqueueNDRangeKernel(q, kernel, 2, offset, global, local, 0, nullptr, nullptr), "clEnqueueNDRangeKernel");のところのglobal,localなどの数値を変えるなどして動かしてみました。

###補足情報(言語/FW/ツール等のバージョンなど)
MacBook Pro 13インチ、OSはel capitanです。

Terminal上で
/System/Library/Frameworks/OpenCL.framework/Libraries/openclc -c -o kernel2.cl.gpu_32.bc -arch gpu_32 -emit-llvm kernel2.cl
g++ -O3 -std=c++11 -framework opencl main3.cpp -o test
./test
で実行しました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

C

1//ここからカーネル部分 2//kernel2.cl 3kernel 4 void addone(global float* data,const int n) { 5 int index = get_global_id(1); // ← ココ、0じゃないの? 6 int index2 = get_global_id(1); 7 printf("index = %d , index2 = %d \n",index,index2); 8 data[index*n+index2] += 1.0f; 9 }

投稿2017/01/11 01:26

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

khsh

2017/01/11 01:32

申しわけありません。カーネルの部分を色々試しており、修正するのを忘れていました。 int index = get_global_id(1) を int index = get_global_id(0) に変えても問題は解決しませんでした。
episteme

2017/01/11 01:35

kernel内の printf はどんな出力するんですか? 10*10 = 100行出力されますか?
episteme

2017/01/11 01:46

もうひとつ。 EC(clSetKernelArg(kernel, 1, sizeof(cl_mem), &n), "clSetKernelArg");                ↑sizeof(int) じゃないの?
khsh

2017/01/11 02:08

index = 0 , index2 = 0 index = 0 , index2 = 0 index = 0 , index2 = 0 index = 1 , index2 = 1 index = 0 , index2 = 0 index = 0 , index2 = 0 index = 1 , index2 = 1 index = 2 , index2 = 2 途中省略 index = 9 , index2 = 9 index = 8 , index2 = 8 index = 9 , index2 = 9 index = 9 , index2 = 9 index = 9 , index2 = 9 index = 8 , index2 = 8 のような出力で100行出力されていました。 EC(clSetKernelArg(kernel, 1, sizeof(cl_mem), &n), "clSetKernelArg")を EC(clSetKernelArg(kernel, 1, sizeof(int), &n), "clSetKernelArg")に変えましたが結果は変わりませんでした。
episteme

2017/01/11 02:29 編集

...わからんなー、100行書かれたんなら n*n 個のkernelが動いたわけで、なんで get_global_id() が同じ値になるんやろ。get_work_dim() は2を返してくれますか? # ごめんなさい、一昨年OpenCLからCUDAに寝返ったので記憶が曖昧。これ以上はアドバイスできんです。
khsh

2017/01/11 03:22

kernel2.cl上でget_work_dim()をしてみたところget_work_dim() は2を返していました。 アドバイスありがとうございました。
episteme

2017/01/11 03:28

ダメ元で clEnqueueNDRangeKernelの第6パラメータ: local を NULL にすれば?
khsh

2017/01/11 03:43

clEnqueueNDRangeKernelの第6パラメータをNULLにしてみましたが、結果は変わりませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問