Berimsel bilimlerde Duff aygıtı, Assembly Dilinde yüksek başarıma izin veren döngü çözme tekniğini kullanan seri kopyalama yordamına ait bir uygulamadır. Tom Duff'ın Lucasfilm'de görev yaptığı Kasım 1983'te bulguladığı yöntem, C programlama dilindeki switch yapısının en ilginç kullanımlarından birini oluşturmaktadır. Duff, yalnızca bu yöntemi bulguladığını savunmakta ve genel döngü çözme yöntemi üzerinde herhangi bir hak iddia etmemektedir.
Seri kopyalama işleminin olağan uygulaması aşağıdaki gibidir.
do { /* count > 0 koşulunun sağlandığı varsayılıyor */
*hedef = *kaynak++; /* ''hedef'' imleci artırılMAmaktadır */
} while (--toplam > 0);
hedef
imlecinin artırılmamasının nedeni Duff'ın kopyalama için tek yazmaç kullanıyor olmasıdır. Bu işlem, hedef
imlecinin volatile
ifadesiyle tanımlanmasıyla da yerine getirilebilir.
Duff, bu betiğin başarımını artırmaya çalışırken bunun switch ve döngü yapılarını iç içe geçirmekle de sağlanabileceğini görmüştür.
dsend(hedef, kaynak, toplam)
char *hedef, *kaynak;
int toplam;
{
int n = (toplam + 7) / 8;
switch (toplam % 8) {
case 0: do { *hedef = *kaynak++;
case 7: *hedef = *kaynak++;
case 6: *hedef = *kaynak++;
case 5: *hedef = *kaynak++;
case 4: *hedef = *kaynak++;
case 3: *hedef = *kaynak++;
case 2: *hedef = *kaynak++;
case 1: *hedef = *kaynak++;
} while (--n > 0);
}
}
Bir kopyalama işlemi sırasında gerekli karşılaştırma sayısını en aza indirgemeye yarayan assembly yordamını temel alan Duff aygıtı, C'de uygulandığında açık bir fark yaratmıştır. Switch ifadesinin dildeki esnek tanımı bu yöntemin C'nin tüm kurallarıyla uyuşmasına yardımcı olmuştur. Aygıtın bulgulanması C Programlama Dili'nin ilk baskısından hemen sonraya rastlamakta ve aygıtın sözdizimi kitapta öngörülen switch kullanımıyla örtüşmektedir. Break ifadesinin bulunmadığı switch betiklerinde akışın kesintisiz biçimde sürdüğü göz önüne alındığında Duff aygıtının sıralı kaynaklardan çıktı yazmaçlarına toplam kopyaları aktardığı görülür. Burada, toplam değişkeninin 0'dan büyük olması zorunludur.
Çoğu derleyici switch'i bir sıçrama tablosuna çevirecektir. C'nin case ifadesindeki öntanımlı akış yordamı dilin en çok tartışılan özelliklerindendir. Duff bu konuda şunları söylemiştir: "Bu betik, tartışmaya bir yerden giriyor ancak bunun olumlu mu olumsuz mu olduğu konusunda emin değilim."[1]
Hızı artıran ana etken bir döngü içinde yapılan karşılaştırmaların sayısını azaltan döngü çözme yöntemidir. Switch/case ifadesi toplam verinin çözülen işlem sayısına bölümünden kalan kısmını işlemektedir (8'li döngü çözmenin uygulandığı örnekte switch/case ifadesi kalan 1–7 baytlık bölümü hedef almaktadır).
Kalan bölümün bu biçimde işlenmesi tüm sistem ya da derleyicilerde aynı başarımı göstermeyebilir. Kimi durumlarda iki ayrı döngü (ilk döngü ana kopyalamayı yaparken ikinci döngü kalan veriyi işler) kullanmak daha iyi sonuç verebilir. Sorun, derleyicinin aygıtı doğru bir biçimde hızlandırmasına indirgenebilir ancak bu kullanımın kimi sistemlerde ardışıklama ve sıçrama tahminini olumsuz etkileyebileceği düşünülmektedir. Bu nedenle, bu aygıtın birlikte kullanılacağı sistem, hızlandırma değişkenleri ve derleyicinin iyi seçilmesi gerekmektedir.
Bir konumdan diğerine kopyalama yapabilmek için hedef imlecinin aşağıda gösterildiği gibi sürekli artırılması gerekmektedir.
*hedef++ = *kaynak++;
Aygıtın bu sürümü Bjarne Stroustrup'un C++ Programlama Dili adlı kitabının "Bu Kod Ne Yapıyor?" bölümünde, dille yeni tanışan programcılara çıktı yazmaçlarının işlevleri hakkında bilgi vermek amacıyla gösterilmiştir. Ne var ki, C kütüphanesinde bulunan memcpy işlevi tam olarak bu işi yapmaktadır. Farklı sistemler için başarım artırıcı teknikler içeren bu işlev yukarıda gösterilen betikten daha hızlı çalışmaktadır.