Увеличение достигнутой занятости не увеличивает линейно скорость вычислений

У меня была программа CUDA, в которой регистры ядра ограничивали максимальную теоретическую достигаемую занятость до 50%. Поэтому я решил использовать разделяемую память вместо регистров для тех переменных, которые были постоянными между блочными потоками и были почти доступны только для чтения на протяжении всего запуска ядра. Я не могу предоставить здесь исходный код; То, что я сделал, концептуально было примерно таким:

Моя начальная программа:

__global__ void GPU_Kernel (...) {
    __shared__ int sharedData[N]; //N:maximum amount that doesn't limit maximum occupancy
    int r_1 = A; //except for this first initialization, these registers don't change anymore
    int r_2 = B;
    ...
    int r_m = Y;

    ...   //rest of kernel;
}

Я изменил вышеуказанную программу на:

__global__ void GPU_Kernel (...) {
    __shared__ int sharedData[N-m];
    __shared__ int r_1, r_2, ..., r_m;
    if ( threadIdx.x == 0 ) {
        r_1 = A;
        r_2 = B;
        ...
        r_m = Y; //last of them
    }
    __syncthreads();
    ...   //rest of kernel
}

Теперь потоки деформации внутри блока выполняют широковещательное чтение для доступа к вновь созданным переменным общей памяти. В то же время потоки не используют слишком много регистров для ограничения достигнутой занятости.

Вторая программа имеет максимальную теоретическую достигнутую занятость, равную 100%. В реальных запусках средняя достигнутая занятость для первых программ составляла ~ 48%, а для второй - около ~ 80%. Но проблема в том, что увеличение скорости сети составляет примерно от 5% до 10%, что намного меньше, чем я ожидал, учитывая улучшенную загружаемость. Почему эта корреляция не линейна?

Рассматривая приведенное ниже изображение из технического документа Nvidia, я подумал, что когда достигнутая занятость составляет% 50, например, половина ядер SMX (в новых архитектурах) простаивает одновременно, потому что чрезмерные ресурсы, запрошенные другими ядрами, мешают им работать. активный. Мое понимание ошибочно? Или это неполное объяснение вышеупомянутого явления? Или это добавлено __syncthreads(); и стоимость доступа к разделяемой памяти?

введите описание изображения здесь


person Farzad    schedule 02.12.2013    source источник


Ответы (1)


Почему эта корреляция не линейна?

Если вы уже ограничили пропускную способность памяти или вычислили ее, и любая из этих границ близка к теоретической производительности устройства, улучшение занятости может не сильно помочь. Повышение загруженности обычно помогает, когда ни один из них не ограничивает производительность вашего кода (то есть вы не достигли пикового уровня использования пропускной способности памяти или пиковых вычислений). Поскольку вы не предоставили никакого кода или каких-либо показателей для своей программы, никто не может сказать вам, почему она не ускорилась еще больше. Инструменты профилирования могут помочь вам найти ограничения производительности.

Возможно, вас заинтересует пара веб-семинаров:

Оптимизация CUDA: определение ограничителей производительности, доктор Паулюс Мицикявичюс

CUDA Warps и соображения занятости + прямая трансляция с доктором Джастином Луитдженсом, NVIDIA

В частности, просмотрите слайд 10 со второго веб-семинара .

person Robert Crovella    schedule 02.12.2013