2

私はAMP C++ の初心者です。「parallel_for_each」関数内で「memcpy」を使用するとすべて正常に動作しますが、それがベスト プラクティスではないことはわかっています。「copy_to」を使用しようとしましたが、例外が発生します。以下は、私が問題を抱えているという問題に焦点を当てた単純化されたコードに従います。前もって感謝します。

typedef std::vector<DWORD> CArrDwData;

class CdataMatrix
{
public:
    CdataMatrix(int nChCount) : m_ChCount(nChCount)
    {
    }

    void SetSize(UINT uSize)
    {
        // MUST be multiple of m_ChCount*DWORD
        ASSERT(uSize%sizeof(DWORD) == 0);
        m_PackedLength = uSize/sizeof(DWORD);
        m_arrChannels.resize(m_ChCount*m_PackedLength);
    }

    UINT GetChannelPackedLen() const
    {
        return m_PackedLength;
    }
    const LPBYTE GetChannelBuffer(UINT uChannel) const
    {
        CArrDwData::const_pointer cPtr = m_arrChannels.data() + m_PackedLength*uChannel;

        return (const LPBYTE)cPtr;
    }

public:
    CArrDwData m_arrChannels;

protected:
    UINT m_ChCount;
    UINT m_PackedLength;
};

void CtypDiskHeader::ParalelProcess()
{
    const int nJobs = 6;
    const int nChannelCount = 3;
    UINT uAmount = 250000;
    int vch;

    CArrDwData arrCompData;

    // Check buffers sizes
    ASSERT((~uAmount & 0x00000003) == 3);   // DWORD aligned
    const UINT uInDWSize = uAmount/sizeof(DWORD);   // in size give in DWORDs

    CdataMatrix arrChData(nJobs);

    arrCompData.resize(nJobs*uInDWSize);
    vector<int> a(nJobs);
    for(vch = 0; vch < nJobs; vch++)
        a[vch] = vch;

    arrChData.SetSize(uAmount+16); // note: 16 bytes or 4 DWORDs larger than uInDWSize

    accelerator_view acc_view = accelerator().default_view;

    Concurrency::extent<2> eIn(nJobs, uInDWSize);
    Concurrency::extent<2> eOut(nJobs, arrChData.GetChannelPackedLen());

    array_view<DWORD, 2> viewOut(eOut, arrChData.m_arrChannels);

    array_view<DWORD, 2> viewIn(eIn, arrCompData);

    concurrency::parallel_for_each(begin(a), end(a), [&](int vch)
    {
        vector<DWORD>::pointer ptr = (LPDWORD)viewIn(vch).data();
        LPDWORD bufCompIn = (LPDWORD)ptr;
        ptr = viewOut(vch).data();
        LPDWORD bufExpandedIn = (LPDWORD)ptr;

        if(ConditionNotOk())
        {
            // Copy raw data bufCompIn to bufExpandedIn

            // Works fine, but not the best way, I suppose:
            memcpy(bufExpandedIn, bufCompIn, uAmount);

            // Raises exception:
            //viewIn(vch).copy_to(viewOut(vch));
        }
        else
        {
            // Some data processing here
        }
    });
}
4

2 に答える 2

0

とは何の関係もありませんparallel_for_eachが、 の既知のバグのようarray_view::copy_toです。次の投稿を参照してください。

concurrency::copy と array_view プロジェクションの相互作用に関する好奇心

view_as()代わりに明示的に使用してこれを修正できます。あなたの場合、コードは次のようになるはずです。

viewIn(vch).copy_to(viewOut(vch));

// Becomes...

viewIn[vch].view_as<1>(concurrency::extent<1>(uInDWSize)).copy_to(viewOut(vch));

あなたの例をコンパイルできないため、これを確認できませんでしたが、同様のコードから例外を取得し、view_as().

C++ AMP カーネル内でデータをコピーする場合は、一連のスレッドで割り当て操作として行う必要があります。次のコードは、 の最初の 500 要素をsource小さい方のdest配列にコピーします。

array<int, 1> source(1000);
array<int, 1> dest(500);

parallel_for_each(source.extent, [=, &source, &dest](index<1> idx)
{
    if (dest.extent.contains(idx))
        dest[idx] = source[idx];
});
于 2014-09-26T21:17:22.317 に答える
0

私の責任です。元のコードでは、viewOut(vch) の範囲は viewIn(vch) の範囲よりも少し大きくなっています。この方法を使用すると、例外「runtime_exception」が発生します。それをキャッチすると、次のメッセージ xcp.what() = "エクステントが一致しないため、コピーに失敗しました" が提供されます。

元のコードを次のように置き換えてコードを修正しました。ソースエクステントのみをコピーします。それが必要です。ただし、AMP を制限せずにコンパイルするだけです。

于 2014-09-27T23:00:25.697 に答える