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

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

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

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

CPU

CPUは、コンピュータの中心となる処理装置(プロセッサ)で中央処理装置とも呼ばれています。プログラム演算や数値計算、その他の演算ユニットをコントロール。スマホやPCによって内蔵されているCPUは異なりますが、処理性能が早いほど良いとされています。

解決済

CPUで画像を並列処理した際にノイズが入ってしまう

kyo46810
kyo46810

総合スコア2

C

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

CPU

CPUは、コンピュータの中心となる処理装置(プロセッサ)で中央処理装置とも呼ばれています。プログラム演算や数値計算、その他の演算ユニットをコントロール。スマホやPCによって内蔵されているCPUは異なりますが、処理性能が早いほど良いとされています。

1回答

0評価

0クリップ

304閲覧

投稿2022/04/03 15:45

問題

c言語とopenmpでCPUで並列に画像を90度回転させるプログラムを作った際に、実行結果の画像(下に記載)にゴマ塩ノイズが含まれてしまいます。コンパイル時に特にエラーは出ず、画像をピクセルの配列として受け取って、各要素の位置を入れかえているだけなので、計算のプログラムが間違えていて要素の値が0~255の範囲外になってしまっていることはないと思います。また、同様の計算をopenmpなしの処理、コンパイルオプションで-openmpを入れないとき(画像は省略)、cudaによるGPU並列で行った結果にはノイズは含まれません。

ここからは私の推測なのですが、CPUが故障しているのではないかと思っています。普段使いしている分には何もバグのようなことはないですが、Apexをしていると音飛びやゲーム画面が閉じてしまうことがあります。(PCのスペックは足りていると思います。)

上記の問題を調べてもわからなかったので何か少しでも原因に心当たりのある方、助けていただきたいです。よろしくお願いします。

環境

OS:windows11 Home
CPU:AMD Ryzen 5 5600X 6-Core Processor 3.70 GHz
GPU:NVIDIA GeForce RTX 3060Ti
RAM:16GB

ソースコード

C言語(openmpなし)

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <omp.h> #define Nx 1024 #define Ny 1024 int main() { int i, j, ID, ID_in, ID_out; double start, end; /* 時間計測用 */ float* h_IMG_input; /* 入力データ用 */ float* h_IMG_output; /* 出力データ用 */ h_IMG_input = (float*)malloc(sizeof(float) * Nx * Ny); /* 入力データ用 */ h_IMG_output = (float*)malloc(sizeof(float) * Nx * Ny); /* 出力データ用 */ memset(h_IMG_input, 0, sizeof(float) * Nx * Ny); /* 入力データ用 */ memset(h_IMG_output, 0, sizeof(float) * Nx * Ny); /* 出力データ用 */ //ファイルよりデータ入力 FILE* fp; /* 入出ファイル用 */ fp = fopen("./lenna1024.img", "r"); /* 読込みモードでファイルをオープンする */ if (fp == NULL) { printf("ファイルを開くことが出来ませんでした.\n"); return; } for (j = 0; j < Ny; j++) { for (i = 0; i < Nx; i++) { ID = i + j * Nx; fscanf(fp, "%f", &(h_IMG_input[ID])); /* 1行読む → h_IMG_input[ID])に入れる */ } } fclose(fp); /* ファイルをクローズする */ //時間計測開始 start = omp_get_wtime(); // 画像を90度右回りに回転させる for (j = 0; j < Ny; j++) { for (i = 0; i < Nx; i++) { ID_in = i + j * Nx; ID_out = j + (1023 - i) * Nx; h_IMG_output[ID_out] = h_IMG_input[ID_in]; } } //時間計測終了 end = omp_get_wtime(); printf("\nCalculation End\n"); printf("\n Processing Time : %.3f [msec]\n", 1e3 * (end - start)); //出力用データをファイルに書き込む fp = fopen("a_c.img", "w"); /* 書込みモードでファイルをオープンする */ if (fp == NULL) { printf("ファイルを作れませんでした"); return; /* ここでプログラム終了 */ } for (j = 0; j < Ny; j++) { for (i = 0; i < Nx; i++) { ID = i + j * Nx; fprintf(fp, "%d\n", (unsigned char)h_IMG_output[ID]); /* 1行書込み → h_IMG_output[ID])に入れる */ } } fclose(fp); //メモリ解放 free(h_IMG_input); free(h_IMG_output); return 0; }

実行結果の画像
イメージ説明

C言語(Openmp)

上記のコードと画像処理の部分以外は同じ // 画像を90度右回りに回転させる #pragma omp parallel for private(i) for (j = 0; j < Ny; j++) { for (i = 0; i < Nx; i++) { ID_in = i + j * Nx; ID_out = j + (1023 - i) * Nx; h_IMG_output[ID_out] = h_IMG_input[ID_in]; } }

実行結果の画像
イメージ説明

C(cuda)

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <cuda.h> #include <cuda_runtime.h> #include <cuda_runtime_api.h> #define HTH cudaMemcpyHostToHost #define HTD cudaMemcpyHostToDevice #define DTH cudaMemcpyDeviceToHost #define DTD cudaMemcpyDeviceToDevice #define Nx 1024 #define Ny 1024 #define Db_x 16 #define Db_y 16 #define Db_z 1 #define Dg_x (Nx / Db_x) #define Dg_y (Ny / Db_y) #define Dg_z 1 dim3 Db(Db_x, Db_y, Db_z); dim3 Dg(Dg_x, Dg_y, Dg_z); float* h_IMG_input; /* 入力データ用(Host) */ float* h_IMG_output; /* 出力データ用(Host) */ float* d_IMG_input; /* 入力データ用(Device) */ float* d_IMG_output; /* 出力データ用(Device) */ cudaEvent_t start, end; /* 時間計測用 */ float timer; /* 時間計測用 */ int element = sizeof(float) * Nx * Ny; // 画像を右に90度回転させる __global__ void rotate(float* d_IMG_input, float* d_IMG_output) { int X, Y, ID_in, ID_out; X = threadIdx.x + (blockIdx.x * blockDim.x); Y = threadIdx.y + (blockIdx.y * blockDim.y); ID_in = X + Y * Nx; ID_out = Y + (1023 - X) * Nx; d_IMG_output[ID_out] = d_IMG_input[ID_in]; } int main() { int GPU_Num = 0; cudaSetDevice(GPU_Num); printf("convert_color.cu\n"); printf("Nx = %d, Ny = %d\n", Nx, Ny); printf("Number %d GPU working\n", GPU_Num); int i, j, ID; // デバイス(VRAM内)に要素を確保 cudaMalloc((void**)&d_IMG_input, element); cudaMalloc((void**)&d_IMG_output, element); cudaMemset(d_IMG_input, 0, element); cudaMemset(d_IMG_output, 0, element); // ホスト(RAM内)に要素を確保 cudaHostAlloc((void**)&h_IMG_input, element, cudaHostAllocPortable); cudaHostAlloc((void**)&h_IMG_output, element, cudaHostAllocPortable); memset(h_IMG_input, 0, element); memset(h_IMG_output, 0, element); //ファイルよりデータ入力 FILE* fp; /* 入出ファイル用 */ fp = fopen("./lenna1024.img", "r"); /* 読込みモードでファイルをオープンする */ if (fp == NULL) { printf("ファイルを開くことが出来ませんでした.\n"); return 0; } for (j = 0; j < Ny; j++) { for (i = 0; i < Nx; i++) { ID = i + j * Nx; fscanf(fp, "%f", &(h_IMG_input[ID])); /* 1行読む → h_IMG_input[ID])に入れる */ } } fclose(fp); /* ファイルをクローズする */ // 演算時間を計測するためのcudaEventCreateを実行 cudaEventCreate(&start); cudaEventCreate(&end); printf("\nCalculation Start\n"); cudaMemcpy(d_IMG_input, h_IMG_input, element, HTD); // 演算時間を計測するためのcudaEventRecordを実行し計算の開始を記録 cudaEventRecord(start, 0); // 画像を右に90度回転させる rotate<<< Dg, Db >>>(d_IMG_input, d_IMG_output); cudaThreadSynchronize(); // 演算時間を計測するためのcudaEventRecordを実行し計算の終了を記録 cudaEventRecord(end, 0); // 演算時間を算出 cudaEventSynchronize(end); cudaEventElapsedTime(&timer, start, end); printf("\nCalculation End\n"); printf("\nProcessing Time : %.3f [msec]\n", timer); /* File Output */ cudaMemcpy(h_IMG_output, d_IMG_output, element, DTH); //出力用データをファイルに書き込む fp = fopen("a_cuda.img", "w"); /* 書込みモードでファイルをオープンする */ if (fp == NULL) { printf("ファイルを作れませんでした"); return 0; /* ここでプログラム終了 */ } for (j = 0; j < Ny; j++) { for (i = 0; i < Nx; i++) { ID = i + j * Nx; fprintf(fp, "%d\n", (unsigned char)h_IMG_output[ID]); /* 1行書込み → h_IMG_output[ID])に入れる */ } } fclose(fp); cudaFree(d_IMG_input); cudaFree(d_IMG_output); cudaFreeHost(h_IMG_input); cudaFreeHost(h_IMG_output); cudaEventDestroy(start); cudaEventDestroy(end); return 0; }

実行結果の画像
イメージ説明

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

jbpb0

2022/04/03 22:43

ID_inとID_outが、スレッド間で共有されてます
kyo46810

2022/04/04 03:43

おっしゃる通り、forループ内で変数を定義したらできました。ありがとうございます。
kyo46810

2022/04/04 03:50

回答に同様の内容を書き込んでいただいてもよろしいでしょうか。

まだ回答がついていません

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

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

C

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

CPU

CPUは、コンピュータの中心となる処理装置(プロセッサ)で中央処理装置とも呼ばれています。プログラム演算や数値計算、その他の演算ユニットをコントロール。スマホやPCによって内蔵されているCPUは異なりますが、処理性能が早いほど良いとされています。