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

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

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

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

CPU

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

Q&A

解決済

1回答

540閲覧

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

kyo46810

総合スコア2

C

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

CPU

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

0グッド

0クリップ

投稿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なし)

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4#include <omp.h> 5 6#define Nx 1024 7#define Ny 1024 8 9int main() 10{ 11 int i, j, ID, ID_in, ID_out; 12 double start, end; /* 時間計測用 */ 13 14 float* h_IMG_input; /* 入力データ用 */ 15 float* h_IMG_output; /* 出力データ用 */ 16 17 h_IMG_input = (float*)malloc(sizeof(float) * Nx * Ny); /* 入力データ用 */ 18 h_IMG_output = (float*)malloc(sizeof(float) * Nx * Ny); /* 出力データ用 */ 19 20 memset(h_IMG_input, 0, sizeof(float) * Nx * Ny); /* 入力データ用 */ 21 memset(h_IMG_output, 0, sizeof(float) * Nx * Ny); /* 出力データ用 */ 22 23 //ファイルよりデータ入力 24 FILE* fp; /* 入出ファイル用 */ 25 fp = fopen("./lenna1024.img", "r"); /* 読込みモードでファイルをオープンする */ 26 if (fp == NULL) { 27 printf("ファイルを開くことが出来ませんでした.\n"); 28 return; 29 } 30 31 for (j = 0; j < Ny; j++) { 32 for (i = 0; i < Nx; i++) { 33 ID = i + j * Nx; 34 fscanf(fp, "%f", &(h_IMG_input[ID])); /* 1行読む → h_IMG_input[ID])に入れる */ 35 } 36 } 37 38 fclose(fp); /* ファイルをクローズする */ 39 40 //時間計測開始 41 start = omp_get_wtime(); 42 43 // 画像を90度右回りに回転させる 44 for (j = 0; j < Ny; j++) { 45 for (i = 0; i < Nx; i++) { 46 ID_in = i + j * Nx; 47 ID_out = j + (1023 - i) * Nx; 48 h_IMG_output[ID_out] = h_IMG_input[ID_in]; 49 } 50 } 51 52 //時間計測終了 53 end = omp_get_wtime(); 54 printf("\nCalculation End\n"); 55 printf("\n Processing Time : %.3f [msec]\n", 1e3 * (end - start)); 56 57 58 //出力用データをファイルに書き込む 59 fp = fopen("a_c.img", "w"); /* 書込みモードでファイルをオープンする */ 60 61 if (fp == NULL) { 62 printf("ファイルを作れませんでした"); 63 return; /* ここでプログラム終了 */ 64 } 65 66 for (j = 0; j < Ny; j++) { 67 for (i = 0; i < Nx; i++) { 68 ID = i + j * Nx; 69 fprintf(fp, "%d\n", (unsigned char)h_IMG_output[ID]); /* 1行書込み → h_IMG_output[ID])に入れる */ 70 } 71 } 72 73 fclose(fp); 74 75 76 //メモリ解放 77 free(h_IMG_input); 78 free(h_IMG_output); 79 80 return 0; 81} 82

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

C言語(Openmp)

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

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

C(cuda)

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4 5#include <cuda.h> 6#include <cuda_runtime.h> 7#include <cuda_runtime_api.h> 8 9#define HTH cudaMemcpyHostToHost 10#define HTD cudaMemcpyHostToDevice 11#define DTH cudaMemcpyDeviceToHost 12#define DTD cudaMemcpyDeviceToDevice 13 14#define Nx 1024 15#define Ny 1024 16 17#define Db_x 16 18#define Db_y 16 19#define Db_z 1 20 21#define Dg_x (Nx / Db_x) 22#define Dg_y (Ny / Db_y) 23#define Dg_z 1 24 25dim3 Db(Db_x, Db_y, Db_z); 26dim3 Dg(Dg_x, Dg_y, Dg_z); 27 28float* h_IMG_input; /* 入力データ用(Host) */ 29float* h_IMG_output; /* 出力データ用(Host) */ 30 31float* d_IMG_input; /* 入力データ用(Device) */ 32float* d_IMG_output; /* 出力データ用(Device) */ 33 34cudaEvent_t start, end; /* 時間計測用 */ 35float timer; /* 時間計測用 */ 36 37int element = sizeof(float) * Nx * Ny; 38 39// 画像を右に90度回転させる 40__global__ void rotate(float* d_IMG_input, float* d_IMG_output) 41{ 42 int X, Y, ID_in, ID_out; 43 44 X = threadIdx.x + (blockIdx.x * blockDim.x); 45 Y = threadIdx.y + (blockIdx.y * blockDim.y); 46 47 ID_in = X + Y * Nx; 48 ID_out = Y + (1023 - X) * Nx; 49 d_IMG_output[ID_out] = d_IMG_input[ID_in]; 50} 51 52int main() 53{ 54 int GPU_Num = 0; 55 56 cudaSetDevice(GPU_Num); 57 58 printf("convert_color.cu\n"); 59 printf("Nx = %d, Ny = %d\n", Nx, Ny); 60 printf("Number %d GPU working\n", GPU_Num); 61 62 int i, j, ID; 63 64 // デバイス(VRAM内)に要素を確保 65 cudaMalloc((void**)&d_IMG_input, element); 66 cudaMalloc((void**)&d_IMG_output, element); 67 68 cudaMemset(d_IMG_input, 0, element); 69 cudaMemset(d_IMG_output, 0, element); 70 71 // ホスト(RAM内)に要素を確保 72 cudaHostAlloc((void**)&h_IMG_input, element, cudaHostAllocPortable); 73 cudaHostAlloc((void**)&h_IMG_output, element, cudaHostAllocPortable); 74 75 memset(h_IMG_input, 0, element); 76 memset(h_IMG_output, 0, element); 77 78 //ファイルよりデータ入力 79 FILE* fp; /* 入出ファイル用 */ 80 81 fp = fopen("./lenna1024.img", "r"); /* 読込みモードでファイルをオープンする */ 82 if (fp == NULL) { 83 printf("ファイルを開くことが出来ませんでした.\n"); 84 return 0; 85 } 86 87 for (j = 0; j < Ny; j++) { 88 for (i = 0; i < Nx; i++) { 89 ID = i + j * Nx; 90 fscanf(fp, "%f", &(h_IMG_input[ID])); /* 1行読む → h_IMG_input[ID])に入れる */ 91 } 92 } 93 94 fclose(fp); /* ファイルをクローズする */ 95 96 97 // 演算時間を計測するためのcudaEventCreateを実行 98 cudaEventCreate(&start); 99 cudaEventCreate(&end); 100 101 printf("\nCalculation Start\n"); 102 103 cudaMemcpy(d_IMG_input, h_IMG_input, element, HTD); 104 105 // 演算時間を計測するためのcudaEventRecordを実行し計算の開始を記録 106 cudaEventRecord(start, 0); 107 108 109 // 画像を右に90度回転させる 110 rotate<<< Dg, Db >>>(d_IMG_input, d_IMG_output); 111 cudaThreadSynchronize(); 112 113 // 演算時間を計測するためのcudaEventRecordを実行し計算の終了を記録 114 cudaEventRecord(end, 0); 115 116 // 演算時間を算出 117 cudaEventSynchronize(end); 118 cudaEventElapsedTime(&timer, start, end); 119 120 printf("\nCalculation End\n"); 121 122 printf("\nProcessing Time : %.3f [msec]\n", timer); 123 124 /* File Output */ 125 cudaMemcpy(h_IMG_output, d_IMG_output, element, DTH); 126 127 //出力用データをファイルに書き込む 128 fp = fopen("a_cuda.img", "w"); /* 書込みモードでファイルをオープンする */ 129 130 if (fp == NULL) { 131 printf("ファイルを作れませんでした"); 132 return 0; /* ここでプログラム終了 */ 133 } 134 135 for (j = 0; j < Ny; j++) { 136 for (i = 0; i < Nx; i++) { 137 ID = i + j * Nx; 138 fprintf(fp, "%d\n", (unsigned char)h_IMG_output[ID]); /* 1行書込み → h_IMG_output[ID])に入れる */ 139 } 140 } 141 142 fclose(fp); 143 144 cudaFree(d_IMG_input); 145 cudaFree(d_IMG_output); 146 147 cudaFreeHost(h_IMG_input); 148 cudaFreeHost(h_IMG_output); 149 150 cudaEventDestroy(start); 151 cudaEventDestroy(end); 152 153 return 0; 154} 155

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

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

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

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

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

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

jbpb0

2022/04/03 22:43

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

2022/04/04 03:43

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

2022/04/04 03:50

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

回答1

0

ベストアンサー

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

投稿2022/04/04 04:04

jbpb0

総合スコア7651

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

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

kyo46810

2022/04/04 04:07

ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問