Данные перекрытия CUDA не работают

Использование пар для перекрытия передачи данных с выполнением ядра не работает в моей системе.

Здравствуйте, я хочу использовать перекрывающиеся вычисления и передачи данных в CUDA, но я не могу. Справочный документ NVIDIA гласит, что при использовании потоков возможны перекрывающиеся вычисления и передача данных. но моя система не работает Пожалуйста, помогите мне.

Моя система ниже

  • ОС: Windows 7 64bit
  • CUDA: версия 5.0.7
  • Комплект разработчика: Visual studion 2008
  • GPU: GTX 680

Я получаю профиль Посмотреть это нравится

Я не получаю перекрытия, код ниже:

    -new pinned memory 
        cudaHostAlloc((void **)&apBuffer, sizeof(BYTE)*lBufferSize,cudaHostAllocDefault);
    -call function

   //Input Data
    for(int i=0;i<m_n3DChannelCnt*m_nBucket;++i)
    {
        cudaErrorChk_Return(cudaMemcpyAsync(d_ppbImg[i],ppbImg[i],sizeof(BYTE)*m_nImgWidth*m_nImgHeight,cudaMemcpyHostToDevice,m_pStream[i/m_nBucket]));
    }
   //Call Function
    for(int i=0;i<m_n3DChannelCnt ;++i)
    {KernelGetVis8uObjPhsPhs<<<nBlockCnt,nThreadCnt,0,m_pStream[i]>>>(d_ppbVis[i],d_ppbAvg[i],d_ppfPhs[i],d_ppfObj[i],d_ppbAmp[i]
                                            ,nTotalSize,d_ppstRefData[i],d_ppbImg[i*m_nBucket],d_ppbImg[i*m_nBucket+1],d_ppbImg[i*m_nBucket+2],d_ppbImg[i*m_nBucket+3]
                                            ,fSclFloatVis2ByteVis);

    }
   //OutputData
    for(int i=0;i<m_n3DChannelCnt;++i)
    {
        if(ppbVis && ppbVis[i]) cudaErrorChk_Return(cudaMemcpyAsync(ppbVis[i],d_ppbVis[i],sizeof(BYTE)*m_nImgWidth*m_nImgHeight,cudaMemcpyDeviceToHost,m_pStream[i]));
        if(ppbAvg && ppbAvg[i]) cudaErrorChk_Return(cudaMemcpyAsync(ppbAvg[i],d_ppbAvg[i],sizeof(BYTE)*m_nImgWidth*m_nImgHeight,cudaMemcpyDeviceToHost,m_pStream[i]));
        if(ppfPhs && ppfPhs[i]) cudaErrorChk_Return(cudaMemcpyAsync(ppfPhs[i],d_ppfPhs[i],sizeof(float)*m_nImgWidth*m_nImgHeight,cudaMemcpyDeviceToHost,m_pStream[i]));
        if(ppfObj && ppfObj[i]) cudaErrorChk_Return(cudaMemcpyAsync(ppfObj[i],d_ppfObj[i],sizeof(float)*m_nImgWidth*m_nImgHeight,cudaMemcpyDeviceToHost,m_pStream[i]));
        if(ppbAmp && ppbAmp[i]) cudaErrorChk_Return(cudaMemcpyAsync(ppbAmp[i],d_ppbAmp[i],sizeof(BYTE)*m_nImgWidth*m_nImgHeight,cudaMemcpyDeviceToHost,m_pStream[i]));

    }

Пожалуйста, дайте мне знать о том, почему профилировщик не показывает перекрытие выполнения ядра и передачи данных.

3 ответа

Вы должны призвать cudaMemcpyAsync() и ядро ​​запускается в правильном порядке. До возможности вычисления 3.5 существовала только одна очередь для запуска операций на стороне устройства, и они не переупорядочивались. Объедините фазы "Call Function" и "OutputData" в нечто вроде

//Call Function and OutputData
for(int i=0;i<m_n3DChannelCnt ;++i)
{KernelGetVis8uObjPhsPhs<<<nBlockCnt,nThreadCnt,0,m_pStream[i]>>>(d_ppbVis[i],d_ppbAvg[i],d_ppfPhs[i],d_ppfObj[i],d_ppbAmp[i]
                                        ,nTotalSize,d_ppstRefData[i],d_ppbImg[i*m_nBucket],d_ppbImg[i*m_nBucket+1],d_ppbImg[i*m_nBucket+2],d_ppbImg[i*m_nBucket+3]
                                        ,fSclFloatVis2ByteVis);

    if(ppbVis && ppbVis[i]) cudaErrorChk_Return(cudaMemcpyAsync(ppbVis[i],d_ppbVis[i],sizeof(BYTE)*m_nImgWidth*m_nImgHeight,cudaMemcpyDeviceToHost,m_pStream[i]));
    if(ppbAvg && ppbAvg[i]) cudaErrorChk_Return(cudaMemcpyAsync(ppbAvg[i],d_ppbAvg[i],sizeof(BYTE)*m_nImgWidth*m_nImgHeight,cudaMemcpyDeviceToHost,m_pStream[i]));
    if(ppfPhs && ppfPhs[i]) cudaErrorChk_Return(cudaMemcpyAsync(ppfPhs[i],d_ppfPhs[i],sizeof(float)*m_nImgWidth*m_nImgHeight,cudaMemcpyDeviceToHost,m_pStream[i]));
    if(ppfObj && ppfObj[i]) cudaErrorChk_Return(cudaMemcpyAsync(ppfObj[i],d_ppfObj[i],sizeof(float)*m_nImgWidth*m_nImgHeight,cudaMemcpyDeviceToHost,m_pStream[i]));
    if(ppbAmp && ppbAmp[i]) cudaErrorChk_Return(cudaMemcpyAsync(ppbAmp[i],d_ppbAmp[i],sizeof(BYTE)*m_nImgWidth*m_nImgHeight,cudaMemcpyDeviceToHost,m_pStream[i]));

}

Вы сможете перекрывать запуск ядра только первой или последней копией памяти, так как у вас есть пять cudaMemcpyAsync() звонки внутри потока, которые снова не переупорядочиваются. Выделите все пять массивов непрерывно в памяти, чтобы вы могли передавать их одним cudaMemcpyAsync(),

Однако в целом я замечаю, что передача данных занимает гораздо больше времени, чем ядро, поэтому перекрывающиеся вычисления и копирование обеспечат лишь незначительное ускорение в вашем случае.

Возможно, вы захотите проверить, работает ли ваш код должным образом (т.е. с перекрытием) в LINUX. Я только что столкнулся с той же проблемой и обнаружил, что в WINDOWS могут быть некоторые проблемы (либо в драйвере NVIDIA, либо в самой Windows), которые мешают перекрытию потоковой передачи CUDA.

Вы можете попробовать и проверить, работает ли пример "simpleStreams" в SDK с перекрытием на вашем компьютере. В моем случае "simpleStream", работающий в Windows, вообще не перекрывается, но отлично работает в Linux. Если быть точным, я использую CUDA 5.0 + VS2010 на Fermi GTX570.

TL;DR: проблема вызвана опцией задержки WDDM TDR в Nsight Monitor! Если установлено значение false, проблема появляется. Вместо этого, если вы установите значение задержки TDR на очень большое число, а для опции "enabled" установлено значение true, проблема исчезнет.

Читайте ниже о других (более старых) шагах, которые следовали до тех пор, пока я не пришел к решению выше, и некоторых других возможных причинах.

Я только недавно смог в основном решить эту проблему! Это специфично для окон и аэро, я думаю. Пожалуйста, попробуйте эти шаги и опубликуйте свои результаты, чтобы помочь другим! Я попробовал это на GTX 650 и GT 640.

Прежде чем что-либо предпринять, рассмотрите возможность использования встроенного gpu (в качестве дисплея) и дискретного gpu (для вычислений), поскольку существуют определенные проблемы с драйвером nvidia для windows! Когда вы используете встроенный gpu, указанные драйверы загружаются не полностью, поэтому многие ошибки устраняются. Также во время работы поддерживается отзывчивость системы!

  1. Убедитесь, что проблема параллелизма не связана с другими проблемами, такими как старые драйверы (в том числе версия BIOS), неправильный код, неработоспособное устройство и т. Д.
  2. Перейти к компьютеру> свойства
  3. Выберите дополнительные настройки системы на левой стороне
  4. Перейти на вкладку "Дополнительно"
  5. В настройках производительности нажмите
  6. На вкладке "Визуальные эффекты" выберите маркер "настроить для лучшей производительности".

Это отключит аэро и почти все визуальные эффекты. Если эта конфигурация работает, вы можете попробовать включить один за другим поля для визуальных эффектов, пока не найдете точную, которая вызывает проблемы!

Кроме того, вы можете:

  1. Щелкните правой кнопкой мыши на рабочем столе, выберите персонализировать
  2. Выберите тему из основных тем, которые не имеют аэро.

Это также будет работать, как указано выше, но с включенными дополнительными визуальными параметрами. Для моих двух устройств этот параметр также работает, поэтому я сохранил его.

Пожалуйста, когда вы попробуете эти решения, вернитесь сюда и опубликуйте результаты!

Для меня это решило проблему в большинстве случаев (плиточный dgemm, который я сделал), но ОБРАТИТЕ ВНИМАНИЕ, что я все еще не могу правильно запустить "simpleStreams" и достичь параллелизма...

ОБНОВЛЕНИЕ: проблема полностью решена с новой установкой Windows!! Предыдущие шаги улучшили поведение в некоторых случаях, но новая установка решила все проблемы!

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

Другие вопросы по тегам