Duff’s Device

9 ноября 1983 года Том Дафф изобрел «устройство» имени себя. Вот так оно выглядело:

send(to, from, count)
	register short *to, *from;
	register count;
	{
		register n=(count+7)/8;
		switch(count%8){
		case 0:	do{	*to = *from++;
		case 7:		*to = *from++;
		case 6:		*to = *from++;
		case 5:		*to = *from++;
		case 4:		*to = *from++;
		case 3:		*to = *from++;
		case 2:		*to = *from++;
		case 1:		*to = *from++;
			}while(--n>0);
		}
	}

Такая конструкция предназначалась для раскрутки цикла копирования фрагмента памяти в регистр пословно. Развертывание сокращает количество итераций цикла и, как следствие, количество операций сравнения (в данном случае в 8 раз), тем самым слегка повышая производительность.

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

#include 
 
int c = 0;
int a = 10;
 
void foo()
{
    printf("%d ", c++);
}
 
void bar()
{
    printf("%d\n", a);
}
 
int main()
{
    switch (a&3) {
    case 0: do { foo(); bar();
    case 3:      foo(); bar();
    case 2:      foo(); bar();
    case 1:      foo(); bar();
	       } while((a -= 4) >= 0);
    }
    return 0;
}

Самое удивительное в этом всем — вовсе не корявое «столбчатое» форматирование. Удивительно то, что язык позволяет размещать цикл внутри блока switch. Интуитивно нам кажется, что каждый case начинает новый блок, и что нельзя соорудить блок, заключающий в себя несколько case’ов. А приведенный выше пример вообще представляется надругательством над синтаксисом C и здравым смыслом. Но стоит задуматься о том, как именно реализована конструкция switch-case, как сразу все становится на свои места:

// исходный код
switch (a) {
    case 0:
        a++;
        break;
    case 1:
        a--;
}
 
// что происходит на самом деле (примерно)
case_0:
    if (a == 1) goto case_1;
    a++;
    goto end;
case_1:
    a--;
end:

Вот так! Теперь понятно, что внутри конструкции switch можно развернуться от души, чем и не преминул воспользоваться Дафф.

Вынужден разочаровать любителей микрооптимизаций: подобное развертывание циклов выполняется современными компиляторами автоматически, и, скорее всего, намного эффективнее. Компилятор ведь может себе позволить не заботиться о чистоте кода. Так что устройство Даффа теперь интересно разве что любителям истории программирования (вроде меня).

Жаждущих подробностей отправляю к оригинальному сообщению Даффа и статье в Википедии.

УжасноПлохоНормальноХорошоОтлично (Еще не оценили)
Loading ... Loading ...

Оставьте свой отзыв

Или введите OpenId:

XHTML: Можно использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">