parallel_for_each上下文中的数组副本

时间:2014-09-25 15:32:25

标签: c++ vector parallel-processing copy c++-amp

我是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
        }
    });
}

2 个答案:

答案 0 :(得分:0)

parallel_for_each无关,看起来它是array_view::copy_to的已知错误。请参阅以下帖子:

Curiosity about concurrency::copy and array_view projection interactions

您可以使用明确的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内核中复制数据,则需要在一系列线程上执行赋值操作。以下代码将source的前500个元素复制到较小的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];
});

答案 1 :(得分:0)

这是我的错。在原始代码中,viewOut(vch)的范围比viewIn(vch)范围稍大。使用这种方式,它会引发异常&#39; runtime_exception&#39;。捕获它时,它提供以下消息:xcp.what()=&#34;由于范围不匹配而无法复制&#34;。

我修复了代码替换原始代码:viewIn(vch).copy_to(viewOut(vch).section(viewIn(vch).extent)); 它只复制源范围,这就是我需要的。但只能编译没有限制AMP。