1

次の問題があります。

非常に基本的な操作を行うコードがあります。マルチスレッドを使用する関数のボトルネックを回避するために、以前に値を格納したかったため、concurrency::array_view へのポインターを渡しています。問題は、次の構造がコンパイルされないことです。

parallel_for_each((*pixels).extent, [=](concurrency::index<2> idx) restrict(amp)
{
int row=idx[0];
int col=idx[1]; 

    (*pixels)(row, col) = (*pixels)(row, col) * (*taps)(row, col); //this is the problematic place 
});

このケースを解決する方法を知っている人はいますか?メソッドを実行する前にデータを準備する必要があるため、RAM とアクセラレータのメモリ間でデータをコピーするのに時間を費やす余裕がないため、このようにする唯一の方法です。

//編集:

ヘッダー ファイルに関するいくつかの問題を解決した後、次の問題が残ります。

parallel_for_each((*pixels).extent, [=](concurrency::index<2> idx) restrict(amp)
{
int row=idx[0];
int col=idx[1]; 
});

上記のコードは機能しません (例外が発生します)。たとえば、クラスのコンストラクターが一度だけコピーを処理できるように、以前にデータを準備する方法ありますか? ヘッダー ファイルに array_view へのポインターが必要であり、次のようにコンストラクターで初期化する必要があります。

cci_subset.h:

concurrency::array_view<float, 2> *pixels, *taps; 

そして、subset.cpp で:

concurrency::array_view<float, 2> pixels(4, 4, pixel_array); 
... 
concurrency::array_view<float, 2> taps(4, 4, myTap4Kernel_array); 

//編集 2:

parallel_for_each のパラメーターは、値でのみ渡すことができることがわかりました。そのため、クラスを初期化するとき、またはいくつかの引数 (画像データなど) をクラスに渡すときに、CPU から GPU に値をコピーする方法をまだ探しています。

4

1 に答える 1

1

C++ AMP の問題

C++ AMP は、GPU 上のデータを参照するための 2 つのコア データ型をサポートします

配列はアクセラレータのデータを表します。1 つのステップで作成してデータを入力することも、後で作成してデータを入力することもできます。どちらの場合でも、いくつかの計算が実行された後、ほぼ確実に結果を配列から CPU にコピーして、アプリケーションの他の部分で使用できるようにします。

配列のみを使用して便利なアプリケーションを作成することもできますが、C++ AMP は array_view も提供します。これは、配列を直接操作するよりも便利な機能をサポートすることがよくあります。array_view は、アクセラレータにとっては配列のように見えますが、アクセラレータとの間でデータをコピーするための手間が省けます。

array_view と配列の関係は、参照とそれが参照するオブジェクトの関係に似ています (正確ではありません)。参照と同様に、配列ビューは作成時に初期化する必要があります。また、参照と同様に、array_view を変更すると、(最終的には) 作成元のデータが変更されます。ただし、その逆は当てはまりません。array_view の作成元のデータを変更しても、array_view が自動的に変更されない可能性があるため、そのような操作には注意して取り組む必要があります。

From: C++ AMP: 加速された大規模な並列処理

pixelsの使用自体は問題ではないと思います。C++ AMP ラムダのピリオド内でグローバル スコープの変数を使用することはできません。これを回避する方法はありません。C++ AMP コードは、異なるメモリ空間を持つデバイスで実行されています。

ただし、arrayまたはarray_viewオブジェクトを別のメソッドまたはコンストラクターで初期化してから、すべての作業を行う関数に渡すことができます。次のコードは、これらの行に沿って何かを行います。クラスのペアとして宣言され、 で初期化さm_framesれる (C++ AMP) オブジェクトへのポインターの配列です。arrayConfigureFrameBuffers

STL スマート ポインターを使用していることに注意してください。生のポインターよりも強くお勧めします。

class FrameProcessorAmpBase
{
private:
    std::shared_ptr<array<float, 2> m_frame;

public:
    FrameProcessorAmpBase()
    {
    }

void ConfigureFrameBuffers(int width, int height)
{
    m_frame = std::make_shared<array<float, 2>>(height, width)); 
}

最小/最大ヘッダーの問題

これはおそらく、windef.h、またはそれに依存するものを含めているためです。これは、STL ヘッダーと Windows ヘッダーを混在させる場合の既知の問題です。これを「修正」する方法はNOMINMAX、他のインクルードよりも前にファイルの先頭で定義し、STL または AMP で宣言された最小/最大関数を使用することです (restrict(amp)ラムダで使用する最小/最大も定義します)。

#define NOMINMAX

GDI を使用している場合、Windows MIN/MAX マクロが必要なため、GDI にも問題があります。

以下を含むラッパーヘッダーで GIDPlus.h をラップします。

#pragma once

#define NOMINMAX
#include <algorithm>
#ifndef max
    #define min std::min
#endif
#ifndef min
    #define max std::max
#endif
#include <gdiplus.h>
#undef max 
#undef min 
于 2014-01-06T06:35:43.670 に答える