🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
CUDA

CUDAは並列計算プラットフォームであり、Nvidia GPU(Graphics Processing Units)向けのプログラミングモデルです。CUDAは様々なプログラミング言語、ライブラリ、APIを通してNvidiaにインターフェイスを提供します。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

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

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

2回答

1587閲覧

C#による背景のマスク処理の処理速度改善の検討

MaSaKai

総合スコア11

CUDA

CUDAは並列計算プラットフォームであり、Nvidia GPU(Graphics Processing Units)向けのプログラミングモデルです。CUDAは様々なプログラミング言語、ライブラリ、APIを通してNvidiaにインターフェイスを提供します。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

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

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

2クリップ

投稿2021/02/03 06:32

編集2021/02/09 17:35

実現したいこと

背景のマスク処理の速度を改善するために、画像処理をする上で何が足りていないのか知りたい。

前提

この処理がやっている内容としては、人物をイメージセグメンテーションしており、
人物以外は、黒く塗りつぶし、人物のみをカラー画像で表示したい。

発生している問題・エラーメッセージ

背景のマスク処理が遅くてムラが生じてしまう。

図1:ムラが生じている図
図1:腕を上から下におろしている図

該当のソースコード

C#

1 private void MaskColor2Black([In, Out] byte[] pixels, byte[] colorArray, byte[] bodyindex) 2 { 3 4 for (int i = 0; i < colorArray.Length; i++) 5 { 6 7 if (bodyindex[i] == 255) 8 { 9 pixels[i * 4] = 0; 10 pixels[i * 4 + 1] = 0; 11 pixels[i * 4 + 2] = 0; 12 } 13 else 14 { 15 pixels[i * 4] = colorArray[i * 4]; 16 pixels[i * 4 + 1] = colorArray[i * 4 + 1]; 17 pixels[i * 4 + 2] = colorArray[i * 4 + 2]; 18 } 19 pixels[i * 4 + 3] = 255; 20 } 21 }

<ソースコードの説明>

  • colorArrayは、画像フォーマットをBGRAで取得してきたカラー画像
  • pixelsは、画像フォーマットをBGRでcolorArrayから色情報を取得し、この配列を画像として表示
  • bodyindexに人物とそれ以外の情報が格納されており、人物の場合は0 / それ以外は255

試したこと

C#

1 else 2 { 3 pixels[i * 4] = 100; 4 pixels[i * 4 + 1] = 100; 5 pixels[i * 4 + 2] = 100; 6 }
  1. 上記のコードのように** 単色で人物を染めるとムラが生じない **
  2. WPFだとコマンドライン引数が使えない(<=試した限りの情報だけなので根拠不足、訂正があればご教授願います)ことから

OpenMPIなどのCPUを用いた並列処理を行えなかった。(OpenMPも試行してみたが画像の状態に変化なし)
0. GPUを用いた並列処理を実装し、CUDAを用いるためにC++のWrapperを記述したが画像の状態に変化なし
下記に該当コードを示す

C++

1 2__global__ void PrrallelProcessingLoop(unsigned char* pixels, unsigned char* colorArray, unsigned char* bodyindex, int len) { 3 int id = (blockIdx.x * blockDim.x) + threadIdx.x; 4 5 if (id < len) { 6 7 if (bodyindex[id] != 255) { 8 pixels[id * 4] = colorArray[id * 4]; 9 pixels[id * 4 + 1] = colorArray[id * 4 + 1]; 10 pixels[id * 4 + 2] = colorArray[id * 4 + 2]; 11 } 12 else { 13 pixels[id * 4] = 0; 14 pixels[id * 4 + 1] = 0; 15 pixels[id * 4 + 2] = 0; 16 } 17 18 19 pixels[id * 4 + 3] = 255; 20 } 21} 22 23 24void PrrallelProcessing(unsigned char* pixels, unsigned char* colorArray, unsigned char* bodyindex, int len, int len2) 25{ 26 unsigned char* dB; 27 unsigned char* dC; 28 unsigned char* dP; 29 cudaSetDevice(0); 30 31 CUDA_SAFE_CALL(cudaMalloc((void**)&dB, len * sizeof(unsigned char))); 32 CUDA_SAFE_CALL(cudaMalloc((void**)&dC, len2 * sizeof(unsigned char))); 33 CUDA_SAFE_CALL(cudaMalloc((void**)&dP, len2 * sizeof(unsigned char))); 34 35 CUDA_SAFE_CALL(cudaMemcpy(dB, bodyindex, len * sizeof(unsigned char), cudaMemcpyHostToDevice)); 36 CUDA_SAFE_CALL(cudaMemcpy(dC, colorArray, len2 * sizeof(unsigned char), cudaMemcpyHostToDevice)); 37 CUDA_SAFE_CALL(cudaMemcpy(dP, pixels, len2 * sizeof(unsigned char), cudaMemcpyHostToDevice)); 38 //cudaMemcpy(dP, pixels, len * sizeof(unsigned char), cudaMemcpyHostToDevice); 39 40 int th = 1024; 41 int bl = (len / th); 42 dim3 blocks(bl, 1, 1); 43 dim3 threads(th, 1, 1); 44 45 PrrallelProcessingLoop <<<blocks, threads>>> (dP, dC, dB, len); 46 47 cudaDeviceSynchronize(); 48 49 cudaMemcpy(pixels, dP, len2 * sizeof(unsigned char), cudaMemcpyDeviceToHost); 50 51 cudaFree(dB); 52 cudaFree(dC); 53 cudaFree(dP); 54}

補足情報(FW/ツールのバージョンなど)

  • OS : Windows10
  • CUDA 11.2
  • Visual Studio 2019
  • WPF
  • .NETFramework 4.7.2

何か足りない情報があれば適宜おっしゃっていただけると幸いです

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

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

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

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

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

yumetodo

2021/02/04 14:48

そもそも1frameの処理に何msかかっているのか計測されていると思うのですが、それはどうですか?また、bodyindexもどこかで計算していると思うのですが、その処理に引っ張られているということはないという認識でいいですか?画像の大きさを縮小することで状況に改善はみられますか?
MaSaKai

2021/02/09 02:32 編集

返信が遅れて申し訳ありません。 * 1frameは、60[ms]ほどで意図的に15FPSにしています * 上記に記されている該当のソースコードは5[ms]の処理時間です * bodyindexに引っ張られている可能性もありますが、今回は想定しない形で考えていただけると幸いです * 画像の大きさは、縮小しても変わりません
guest

回答2

0

根本的な解決には至りませんでしたが、改善に時間が必要であると考えられたため質問を閉じることにします

投稿2021/02/14 04:32

MaSaKai

総合スコア11

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

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

0

ベストアンサー

正直にいうと、メモリー律速しているような気がしてなりません。局所最適化を一旦脇において、GPGPUするならとくにRAM<->VRAMの転送を排除してください。メモリー転送の様子はたしかプロファイラで見れたはずです。bodyindexなどその他の処理もGPUに持っていくとか、逆にSIMDで処理することにしてGPUを排除するとか、非同期化するとか、そういうことが必要な気がします。PrrallelProcessingLoop単体をどうにかするのは多分筋が悪いように見えます。とにかくこの手の処理はメモリー律速との戦いなので、アルゴリズムレベルでどうにもならなくなったらとにかくメモリーアクセスを排除するか、メモリー転送前後で非同期化してなるべく常にメモリー転送し続けるようにするとか、キャッシュに乗りやすいアクセスをするか、prefetchしてみるとかするより他にないでしょう。

投稿2021/02/09 07:29

yumetodo

総合スコア5852

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

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

MaSaKai

2021/02/09 17:33

回答ありがとうございます。 SIMDの場合、関数を切り分けて非同期処理を施しましたが結果は芳しくありませんでした。 プロファイラを見た際に、CPUとGPU間での転送が多いように見受けられたので、GPGPUの使い方を再度見直してみたいと思います。
yumetodo

2021/02/10 02:33

多少GPUでは不得手な条件分岐が多いコードでもGPUに思い切って持っていってしまうのも手かもしれませんね。転送が減らせるならば。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問