Duff's Device

Published 2025-04-13 18:02 1219 words 7 min read

前端项目通过bridge获取客户端资源,客户端直接返回response对象Win11 光标变白消失解决方案(浏览器开启硬件加速后,在鼠标滑到文本处出现)Terminal里用option/alt + 鼠标点击,就可以让光标到指定位置Duff's Device为 UIControl 实现线程安全的 Block 事件扩展:原理与实践前端代码规范设计模式k8s前端项目利用nginx部署项目不停机Vue3+Vite+history模式+Nginx 部署二级路径iOS开发工具常用代码模板2——数据结构常用代码模板1——基础算法iOS:特殊符号大全HomeBrew 更新报错“fatal- Could not resolve HEAD to a revision”SwiftUI基本控件代码大全——1.欢迎进入软件构建的世界C++ STL简介LeetCode 70 爬楼梯(青蛙跳台阶)深入理解计算机系统(第二版) 家庭作业 第二章Swift Module 如何被全局引用LeetCode 398 随机数索引Vue 的一些指令和缩写LeetCode 486 Predict the Winner(预测赢家)浅谈iOS中的weakCocoaPods组件化——OC/Swift动静态库混用OpenGL 术语当对象接收到不能处理的消息时调用的方法命令行通过ffmpeg剪切视频iOS:如何在UITableView调用reloadData刷新结束后再同步执行后续操作统计iOS工程代码行数CMake 入门及常用变量指令手册LeetCode 6 ZigZag Conversion(Z字转换)LeetCode 106 Construct Binary Tree from Inorder and Postorder Traversal(由中序和后序遍历建立二叉树)LeetCode 5 Longest Palindromic Substring(最长回文字串)LeetCode 8 String to Integer (atoi)Objective-C Type EncodingsObjective-C:为什么分类中不能直接添加属性MeshLab数据结构与算法解析习题2.23数据结构与算法解析习题2.19数据结构与算法解析习题2.16数据结构与算法解析习题2.14数据结构与算法解析习题2.13数据结构与算法解析习题2.12数据结构与算法解析习题2.11:二分查找数据结构与算法解析习题2.10:霍纳法则(Horner's rule)数据结构与算法解析习题2.7数据结构与算法解析习题1.3数据结构与算法解析习题1.2数据结构与算法解析习题1.1centos7 mysql数据库安装和配置Fishhook-源码分析解决Mac下 Cornerstone 无法查看SVN日志的问题UIButton扩大点击范围以及关于响应者链条的思考UILabel中文带行间距的处理,限制行数,计算高度等UITableview调用reload方法时抖动问题C语言指针小结C语言数据类型和const、static关键字iOS 截取整个 scrollview 图片WxWidgets类列表objc源码分析-runtime-classiOS自动化埋点的实现iOS平台编译Ogre游戏引擎库在 Mac OS X 上安装 TensorFlowiPhone 刘海机型UI适配(X、Xs、Xs Max、Xr)关于C语言中的union虚拟机 Linux 上编 slice3r perl Build.PL 报错iOS 沙盒与 BundleCOCOAPODS技巧-创建私有仓库iOS脚本打包 ipa(.app转.ipa)Objective-C 中禁止调用指定的方法iOS 关于 UITextField 的字数限制升级 Mac OS 10.13 High Sierra 后 ruby 报错iOS 框架学习-AsyncSocketSQL语句OC优缺点以及常见bugUIViewController 的生命周期runtime——运行时简单使用iPhone6 Plus上面神秘的缝隙CocoaPods安装和使用教程(更新至Mac High Sierra)UIApplicationiOS 网络小结NSString的各种处理HTTP请求报文和HTTP响应报文,以及工作原理Vim 快捷键整理OC中nil 、NULL、 Nil 、NSNull的区别GCD 使用指南iOS常用数据类型转换关于NSNotificationCenterGit 命令MAC OS 常用技巧Description方法和NSLog函数代码重构OC单例宏Block in Objective-CObjective-C 语法 3Objective-C 语法 2Objective-C 语法 1
This post is not yet available in English. Showing the original.
Duff's Device 是 C 语言中一种经典的循环展开优化技术,由 Tom Duff 于 1983 年在卢卡斯影业开发,旨在解决串口通信等场景下的性能瓶颈。它通过结合 switch 语句的 case fall-through(无 break 的穿透执行)特性与循环展开,减少循环条件判断次数,从

Duff’s Device 是 C 语言中一种经典的循环展开优化技术,由 Tom Duff 于 1983 年在卢卡斯影业开发,旨在解决串口通信等场景下的性能瓶颈。它通过结合 switch 语句的 case fall-through(无 break 的穿透执行)特性与循环展开,减少循环条件判断次数,从而提升数据复制效率。

一、核心原理与代码结构

Duff’s Device 的核心思想是 循环展开(Loop Unrolling) 与 余数处理 的结合:

  1. 循环展开

    将原本逐次处理单个数据的循环改为每次处理多个数据(如 8 次),减少循环条件判断的开销。例如,传统循环每次迭代需执行一次条件判断,而展开后每 8 次操作仅需一次判断。

  2. 余数处理

    当数据总量 count 不是展开倍数(如 8)时,通过 switch 语句的跳转机制,从对应余数位置开始执行剩余操作,确保所有数据均被处理。

经典代码示例:

void duff_copy(char *to, char *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);
    }
}

执行逻辑:

  • 当 count 是 8 的倍数时,从 case 0 进入循环,每次处理 8 个数据,循环次数为 count/8。
  • 当 count 非 8 的倍数时,switch 根据余数跳转到对应 case 标签,先处理余数个数据,再进入完整循环。

二、历史背景与性能优化

  1. 诞生场景 Tom Duff 在编写内存映射 I/O 操作时发现传统循环性能低下:每次循环中的条件判断(如 while (—count > 0))占用了大量时间,成为性能瓶颈。

  2. 性能提升机制

    • 减少无用指令:传统循环中每次迭代需执行递减计数与条件判断,这些指令对实际数据操作无贡献,Duff’s Device 通过展开循环减少此类指令占比。
    • 利用 CPU 并行性:现代 CPU 的指令级并行(ILP)技术(如流水线、分支预测)在循环展开后更高效,减少因频繁分支判断导致的流水线停顿。

性能测试示例: 在早期测试中,Duff’s Device 将循环执行时间从 25.4 秒降至 14.7 秒,提升约 42%。

三、优缺点与争议

  1. 优点

    • 性能提升:在早期硬件和编译器优化不足时显著减少指令开销。
    • 代码紧凑性:通过 switch 和循环的嵌套实现逻辑紧凑。
  2. 缺点

    • 可读性差:非常规的代码结构增加了理解难度,可能引发维护问题。现代编译器优化:现代编译器(如 GCC、Clang)能自动进行循环展开,手动优化可能反被编译器优化策略干扰。
    • 平台依赖性:某些处理器对紧凑循环的优化效果优于展开后的长代码。
  3. 争议

    • 语法合法性:Duff’s Device 利用 C 语言的 switch 穿透特性,虽合法但违背常规编码习惯,被视为对语言特性的“创造性滥用”。
    • 实用性争议:在当今硬件与编译技术下,其性能优势已不明显,更多作为编程技巧案例存在。

四、现代应用与启示

  1. 应用场景

    • 嵌入式系统:在资源受限且编译器优化有限的场景中仍有价值。
    • 教学案例:用于讲解循环展开、编译器优化原理及 C 语言语法特性。
  2. 启示

    • 性能优化思维:鼓励开发者深入理解硬件与编译原理,探索底层优化可能性。
    • 代码可维护性权衡:在追求性能时需评估代码可读性代价,避免过度优化。

更直观的代码

void copy(int src[], int dest[], int size) {
    int rounds = size / 8;
    int i = 0;
    switch (size % 8) {
        case 0: while (rounds != 0) { rounds--; dest[i] = src[i]; i++;
        case 7: dest[i] = src[i]; i++;
        case 6: dest[i] = src[i]; i++;
        case 5: dest[i] = src[i]; i++;
        case 4: dest[i] = src[i]; i++;
        case 3: dest[i] = src[i]; i++;
        case 2: dest[i] = src[i]; i++;
        case 1: dest[i] = src[i]; i++;
        }
    }
}

逻辑:通过 switch 处理余数后,进入 while 循环展开 8 次复制操作,每次循环减少条件判断次数。

总结

Duff’s Device 是 C 语言中一项标志性的优化技术,展示了底层编程的创造力与性能优化思维。尽管其现代实用性受限,但作为理解循环展开、编译器优化及语言特性的经典案例,仍具有重要学习价值。