Table of Contents

C duff's device

C Duff's device is a loop unrolling technique that combines a switch statement inside a while loop, allowing the loop condition and case labels to interact. It eliminates loop overhead by processing multiple iterations per loop cycle, originally invented for fast memory copying.

Use Duff's device when loop overhead matters and you need to process arrays in bulk without conditional branching.

Example

This example demonstrates Duff's device for efficient array copying.

// compile: gcc -O2 -o duffs duffs.c
// run: ./duffs
// description: loop unrolling with Duff's device
 
#include <stdio.h>
#include <string.h>
#include <time.h>
 
// Naive loop: one element per iteration
void copy_simple(int *dst, const int *src, int n) {
    for (int i = 0; i < n; i++) {
        dst[i] = src[i];
    }
}
 
// Duff's device: 8 elements per loop cycle
void copy_duffs(int *dst, const int *src, int n) {
    int count = (n + 7) / 8;  // round up to nearest multiple of 8
 
    switch (n % 8) {
    case 0: do {
        *dst++ = *src++;
    case 7: *dst++ = *src++;
    case 6: *dst++ = *src++;
    case 5: *dst++ = *src++;
    case 4: *dst++ = *src++;
    case 3: *dst++ = *src++;
    case 2: *dst++ = *src++;
    case 1: *dst++ = *src++;
            } while (--count > 0);
    }
}
 
int main() {
    int src[1000], dst[1000];
 
    // Initialize source
    for (int i = 0; i < 1000; i++) {
        src[i] = i;
    }
 
    // Test correctness
    copy_duffs(dst, src, 1000);
    printf("Copy successful: dst[500] = %d\n", dst[500]);
 
    // Benchmark (simple version)
    clock_t start = clock();
    for (int iter = 0; iter < 1000; iter++) {
        copy_simple(dst, src, 1000);
    }
    clock_t simple_time = clock() - start;
 
    // Benchmark (Duff's device)
    start = clock();
    for (int iter = 0; iter < 1000; iter++) {
        copy_duffs(dst, src, 1000);
    }
    clock_t duffs_time = clock() - start;
 
    printf("Simple: %ld cycles\n", simple_time);
    printf("Duffs:  %ld cycles\n", duffs_time);
    printf("Speedup: %.2fx\n", (double)simple_time / duffs_time);
 
    return 0;
}

Common patterns

Loop unrolling principle:

Why Duff's device is confusing:

Modern alternatives:

Practical uses (rare today):

Correctness caveats:

Performance notes:

Readability trade-off: