2012-03-15 2 views
2

Добрый день.Обращение с разворачиваемым контуром

Я хотел бы спросить за вклад в уловках, чтобы обрабатывать развернутые циклы объедков, с оговоркой, что петли достаточно малы, 1-3 раза разворачиванием фактора, например:

EG. учитывая разворачивания фактор B

int i = 0; 
for (; i < N-N%B; i += B) { 
    ... 
} 
// remainder 
for (; i < N; ++i) { 
    ... 
} 

если В 2, я могу сделать следующее:

// remainder 
if (N%2) { 
    .... 
} 

Но что это хороший способ справиться с B>2

+0

Трудно видеть зачем нужен трюк, вы цикл N/B раз, остаток - N% B. Обычно вы оставляете это до генератора кода, он уже знает, как разворачивать циклы. –

+0

Ну, всегда есть * [устройство Даффа] (http://en.wikipedia.org/wiki/Duff's_device) *, но в коде нет ничего плохого. –

+0

На C или на любом языке? Предложенные инструкции могут быть приятными для этого на некоторых языках ассемблера. – harold

ответ

0

Ваш if (N%2) может быть легко расширена до любой коэффициент разблокировки:

for (; i < N-B+1; i += B) { 
    x1; x2; ... xB; 
} 
if (i < N) { 
    x1; 
if (i < N-1) { 
    x2; 
    ... 
if (i < N-B+2) { 
    xB; 
}}} 

Для небольших факторов разворота это может быть более эффективен, чем второй цикл или устройство Даффа.

Эта версия выглядит лучше. GCC 4.6 компилирует почти тот же код из него:

if (i++ < N) { 
    x1; 
if (i++ < N) { 
    x2; 
    ... 
if (i++ < N) { 
    xB; 
}}} 

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

if (N%B > B-2) { 
    x1; 
if (N%B > B-3) { 
    x2; 
    ... 
if (N%B > 0) { 
    xB; 
}}} 
Смежные вопросы