2015-07-10 7 views
1

Поскольку мои указатели все указывают на неперекрывающуюся память, я изо всех сил и заменил мои указатели, переданные ядрам (и их встроенным функциям) на , ограничил и сделал их const тоже, где это возможно. Это, однако, увеличило использование регистров некоторых ядер и уменьшило его для других. Это не имеет для меня никакого смысла.Может ли const * __restrict__ увеличить использование регистра cuda?

Кто-нибудь знает, почему это может быть так?

ответ

5

Да, это может увеличить использование регистра.

Ссылаясь на programming guide для __restrict__:

Эффекты здесь уменьшенное количество обращений к памяти и уменьшение количества вычислений. Это уравновешивается увеличением давления в регистре из-за «кэшированных» нагрузок и общих подвыражений.

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

const __restrict__ может быть полезным в течение по крайней мере 2 причин:

  1. На архитектурах, которые поддерживают его, он может включить компилятор, чтобы обнаружить использование для constant cache, которые могут быть производительностью повышения функции.

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

Сокращение инструкций и доступа к памяти, приводящих к повышенному регистровому давлению, может быть неинтуитивным. Рассмотрим пример, приведенный в вышеприведенном Руководстве по программированию ссылки:

void foo(const float* a, const float* b, float* c) { 
    c[0] = a[0] * b[0]; 
    c[1] = a[0] * b[0]; 
    c[2] = a[0] * b[0] * a[1]; 
    c[3] = a[0] * a[1]; 
    c[4] = a[0] * b[0]; 
    c[5] = b[0]; ... } 

Если мы допускаем указатель ступенчатости в приведенном выше примере, то компилятор не может сделать много оптимизаций, и компилятор, по существу, сводится к выполнению коды точно так же, как написано. Первая строка кода:

c[0] = a[0] * b[0]; 

потребует 3 регистра. Следующая строка кода:

c[1] = a[0] * b[0]; 

также потребует 3 регистра, а потому, что все генерируется, как написано, они могут быть же 3 регистра многоразового использования. Подобное повторное использование регистра может возникнуть для оставшейся части примера, что приводит к низкому общему использованию/давлению в общем регистре.

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

+0

Благодарим за подробный ответ. Думаю, я должен был быть более явным в своем вопросе. В самом деле, это может увеличить использование регистров, что вам приятно объяснить. Но тогда как это может уменьшить использование регистров? – ikku100

+0

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