Устройство Даффа работает на других языках? - PullRequest
7 голосов
/ 03 мая 2009

Много лет назад, работая над сложной графикой ввода / вывода, Том Дафф развернул цикл и создал свое Устройство Даффа следующим образом:

dsend(to, from, count)
char *to, *from;
int count;
{
    int 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);
    }
}

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

Это кодирование происходит непосредственно из мышления на ассемблере и кодирования на C и зависит от провала оператора case в C. Может ли этот вид творчества в чередующихся структурах управления работать на каких-либо других языках?

Ответы [ 5 ]

5 голосов
/ 03 мая 2009

Вы можете сделать это на любом языке, который поддерживает вычисленные операторы GOTO (Fortran, некоторые BASIC и т. Д.)

4 голосов
/ 03 мая 2009

Работает на С ++.

Обратите внимание, что сгенерированный код зависит от вашего компилятора. В частности, когда я скомпилировал устройство Даффа с использованием GCC, нацеленного на архитектуры ARM, полученный ассемблер ARM был неоптимальным (я думаю, что GCC превратил его в таблицу переходов) на любом уровне оптимизации.

В итоге я просто написал код на ассемблере.

3 голосов
/ 03 мая 2009

Я очень успешно использовал его в JavaScript для ускорения обработки больших массивов. Я хотел бы использовать его в C #.

3 голосов
/ 03 мая 2009

Устройство Даффа, по сути, является вычисленным goto, что может быть сделано на многих других языках - конечно, ассемблер (FORTRAN) и пара, поддерживающая их напрямую.

0 голосов
/ 05 января 2017

Даже если это нельзя использовать таким образом, у вас все равно может быть два цикла:

dsend(to, from, count)
char *to, *from;
int count;
{
    int n;
    for(n=0; n!=count/8; n+=8){
        *to = *from++;
        *to = *from++;
        *to = *from++;
        *to = *from++;
        *to = *from++;
        *to = *from++;
        *to = *from++;
        *to = *from++;
    }
    for(; n!=count; n++)
    {
        *to = *from++;
    }
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...