【问题标题】:Array copy in parallel_for_each contextparallel_for_each 上下文中的数组副本
【发布时间】:2014-09-25 15:32:25
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

    这是我的错。在原始代码中,viewOut(vch) 的范围比 viewIn(vch) 范围大一点。使用这种方式,它会引发异常“runtime_exception”。捕获它时,它会提供以下消息 xcp.what() = "Failed to copy because extents do not match"。

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

    【讨论】:

    • 您在上面的代码中没有任何限制说明符。此外,您不能在restrict(amp) 代码中使用memcpy 或copy_to,因为它们本身都不是restrict(amp)。
    • 是的,我知道我的代码不受限制(amp)。因为我写了“但只能在没有受限 AMP 的情况下编译”。如果您知道允许执行与限制(amp)指令兼容的向量复制(输入的范围小于输出的范围)的等效代码,我将非常感激。我在 MSDN 上进行了搜索,但不幸的是找到了包含矢量副本示例的文档。 Rgds。
    【解决方案2】:

    这与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];
    });
    

    【讨论】:

    • 我在原始帖子中犯了一个重大错误,我刚刚修复了它。源数组和目标数组的范围不同。很抱歉给您带来不便,并感谢您的回复。请检查我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 2013-07-10
    • 1970-01-01
    • 1970-01-01
    • 2019-11-16
    • 1970-01-01
    相关资源
    最近更新 更多