2014-09-25 4 views
2

Я очень новичок в AMP C++. Все работает нормально, если я использую «memcpy» внутри функции «parallel_for_each», но я знаю, что это не лучшая практика. Я попытался использовать 'copy_to', но это вызывает исключение. Ниже приведен упрощенный код, который фокусирует внимание на проблеме, что у меня возникают проблемы. Заранее спасибо.Array copy in parallel_for_each context

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

ответ

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().

Если вы хотите скопировать данные в ядро ​​AMC C++, вам необходимо сделать это как операции присваивания для серии потоков. Следующий код копирует первые 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]; 
}); 
+0

Я сделал серьезную ошибку в своем оригинальном посте, и я только что исправил его. Исходный и целевой массивы не имеют такой же степени. Извините за неудобства и благодарю вас за ответ. Пожалуйста, проверьте мой ответ. –

0

Это была моя ошибка. В исходном коде размер viewOut (vch) немного больше, чем размер viewIn (vch). Используя этот способ, он вызывает исключение «runtime_exception». При ловле он отправляет следующее сообщение xcp.what() = "Не удалось скопировать, потому что экстенты не совпадают".

Я исправил код, заменяющий исходный код: viewIn (vch) .copy_to (viewOut (vch) .section (viewIn (vch) .extent)); Он копирует только источник, который мне нужен. Но только компилирует без ограниченный AMP.

+0

У вас нет каких-либо ограничений в вашем коде выше. Кроме того, вы не можете использовать memcpy или copy_to внутри ограничения (amp), потому что ни один из них сам не ограничивает (amp). –

+0

Да, я знаю, что мой код не ограничивает (amp). Потому что я написал «Но только компилирует без ограничений AMP». Я был бы очень признателен, если бы вы знали эквивалентный код, который позволяет выполнять эту векторную копию (ввод с меньшей степенью, чем вывод), совместимый с директивой ограничения (amp). Меня обыскали MSDN, но мне не повезло найти документацию, содержащую примеры экземпляров векторов. Rgds. –