1

特定の関数を使用してピクセルの正確な出力色を決定する畳み込みフィルターを作成しようとしています。parallel_for_eachブロックで使用できる関数を定義できるかどうかは誰にもわかりませんか?

4

2 に答える 2

3

関数は、restrict(amp) を使用して正常にコンパイルするために、いくつかの規則に従う必要があります。1 つ目は、parallel_for_each() セクションで説明したように、それが呼び出す関数を含みます。これらはコード生成時に表示される必要があり、restrict(amp) でマークされている必要があります。リンク時のコード生成を使用していない場合、これは基本的に、おそらくその .cpp ファイルに含まれるヘッダー ファイルから、コンパイル時に同じ .cpp ファイルに存在する必要があることを意味します。両方の .cpp ファイル (関数を呼び出すファイルとそれを実装するファイル) をコンパイルするときとリンクするときに /ltcg を使用している場合は、呼び出し関数と呼び出された関数を別々のファイルに保持できます。

C++ AMP 互換の関数またはラムダは、次のような C++ AMP 互換の型のみを使用できます。

  • 整数
  • 符号なし整数
  • 浮く
  • ダブル
  • int、unsigned int、float、または double の C スタイルの配列
  • concurrency::array_view または concurrency::array への参照
  • C++ AMP 互換の型のみを含む構造体

これは、一部のデータ型が禁止されていることを意味します。

  • bool (ラムダのローカル変数に使用できます)
  • チャー
  • 短い
  • ロングロング
  • 上記の無署名バージョン

(互換性のある型への) 参照とポインターはローカルで使用できますが、ラムダでキャプチャすることはできません。関数ポインタ、ポインタからポインタへのポインタなどは許可されていません。静的変数でもグローバル変数でもありません。

クラスのインスタンスを使用したい場合、クラスはより多くの規則を満たさなければなりません。仮想関数または仮想継承を持たない必要があります。コンストラクタ、デストラクタ、およびその他の非仮想関数を使用できます。メンバー変数はすべて互換性のある型である必要があります。もちろん、それらのクラスが同じ規則を満たしている限り、他のクラスのインスタンスを含めることができます。

amp 互換関数の実際のコードは CPU 上で実行されていないため、慣れ親しんだ特定のことを実行できません。

  • 再帰
  • ポインターのキャスト
  • 仮想機能の使用
  • 新規または削除
  • RTTI または動的キャスト

これは、あなたがやろうとしていることを正確に行う例ですが、タイリングを使用していません。パラメータは、正方形のピクセル マスクのshiftサイズ (半径) です。この例では、配列の端に非常に近い要素の新しい値を計算しようとしません。作業のないこれらの要素でスレッドを無駄にしないために、配列よりも小さい要素parallel_for_eachであるエクステントを取ります。shift * 2修正されたインデックス は、正しい要素を参照する範囲に基づいて値をidc調整します。idx

void MatrixSingleGpuExample(const int rows, const int cols, const int shift)
{
    //  Initialize matrices

    std::vector<float> vA(rows * cols);
    std::vector<float> vC(rows * cols);
    std::iota(vA.begin(), vA.end(), 0.0f);

    //  Calculation

    accelerator_view view = accelerator(accelerator::default_accelerator).default_view;
    double time = TimeFunc(view, [&]()
    {
        array_view<const float, 2> a(rows, cols, vA); 
        array_view<float, 2> c(rows, cols, vC);
        c.discard_data();

        extent<2> ext(rows - shift * 2, cols - shift * 2);
        parallel_for_each(view, ext, [=](index<2> idx) restrict(amp)
        {
            index<2> idc(idx[0] + shift, idx[1] + shift);
            c[idc] = WeightedAverage(idc, a, shift);
        });
        c.synchronize();
    });
}

float WeightedAverage(index<2> idx, const array_view<const float, 2>& data, int shift) 
    restrict(amp)
{
    if (idx[1] < shift || idx[1] >= data.extent[1] - shift)
        return 0.0f;
    float max = fast_math::sqrtf((float)(shift * shift * 2));
    float avg = 0.0;
    float n = 0.0f;
    for (int i = -shift; i <= shift; ++i)
        for (int j = -shift; j <= shift; ++j)
        {
            int row = idx[0] + i;
            int col = idx[1] + i;
            float scale = 1 - fast_math::sqrtf((float)((i * i) * (j * j))) / max;
            avg += data(row,col) * scale;
            n += 1.0f;
        }
    avg /= n;
    return avg;
}
于 2014-01-16T23:37:27.263 に答える
1

はい、CPU コードから同じ関数を呼び出せるようにする場合は、restrict(amp) または restrict(cpu, amp) で関数シグネチャに注釈を付ける必要があります。restrict に関する MSDN ドキュメントを参照してください。

于 2014-01-16T19:10:27.067 に答える