达夫设备/达夫算法(Duff's Device)
主要是下面的代码:
|
register n = (count + 7) / 8; /\* count > 0 assumed \*/ 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); } |
这是个很棒的迂回循环展开法, 由 Tom Duff 在 Lucasfilm 时所设计。它的 ``传统" 形态, 是用来复制多个字节。
这里 count 个字节从 from 指向的数组复制到 to 指向的内存地址 (这是个内存映射的输出寄存器, 这也是为什么它没有被增加)。它把 swtich 语句和复制 8 个字节的循环交织在一起, 从而解决了剩余字节的处理问题 (当 count 不是 8 的倍数时)。相信不相信, 象这样的把 case 标志放在嵌套在 swtich 语句内的模块中是合法的。当他公布这个技巧给 C 的开发者和世界时, Duff 注意到 C 的 swtich 语法, 特别是 ``跌落" 行为, 一直是被争议的, 而 ``这段代码在争论中形成了某种论据, 但我不清楚是赞成还是反对"
函数包含一个switch语句,它的case语句同时位于一个while循环体内(有一个case语句在外面)。switch内的表达式计算被八除的余数。执行开始于while循环内的哪个位置由这个余数决定,最终循环退出,(没有break)。Duff's Device这样就简单漂亮地解决了边界条件的问题。顺便提一下,为什么"case 0"标记在循环外面呢?这样不是打破了对称的美观吗?这样做的唯一理由是为了处理空序列。当余数为零,"case 0"内就需要执行一个多余的测试来判断空序列的可能性。总之,这是个很酷的算法。
达夫设备是一个加速循环语句的C编码技巧。其基本思想是--减少循环测试的执行次数。
如果在一个for循环中,其中操作执行得如果足够快(比如说,一个赋值)——那么测试循环条件占用了循环所用时间的很大部分。循环应该被部分解开,这样数个操作一次完成,测试操作也做的较少。其实,是通过switch语句将要进行的连续循环操作的次数进行了预判(根据擦case语句的位置)然后依次执行,而不必每次都去进行测试条件。
在这里Duff's Device是个新颖的,有创造力的解决方案。这里有一个使用该模型的一个实例:快速拷贝和填充。
Duff's Device对效率的负面影响可能来自于代码膨胀(一些处理器更善于处理紧凑的循环而不是大的循环)和特别的结构。优化器被做成当遇一些更加技巧性的结构时可能会不知所措从而生成比较保守的代码。
其实达夫设备是使用switch语句来控制进入循环的位置。
下面的程序是简单验证达夫设备的执行:
|
#include <stdio.h> #include <stdlib.h> int main(int argc,char**argv){ int n; if(argc<2){ printf("not enough arugment\n"); return -1; } n=atoi(argv[1]); switch(n){ case 0: do {printf("%d ",0); case 1: printf("%d ",1); case 2: printf("%d ",2); case 3: printf("%d ",3); case 4: printf("%d ",4); }while(--n>0); } return 0; } |
从上面的输出结果我们可以清楚的看到,switch语句控制了进入循环的位置。 |
达夫设备/达夫算法(Duff's Device)的更多相关文章
- 冷知识:达夫设备(Duff's Device)效率真的很高吗?
ID:技术让梦想更伟大 作者:李肖遥 wechat链接:https://mp.weixin.qq.com/s/b1jQDH22hk9lhdC9nDqI6w 相信大家写业务逻辑的时候,都是面向if.el ...
- 达夫设备(Duff's Device)
达夫设备设备是一段非常巧妙,看起来非常诡异的c代码,它可以很大的提高程序执行的效率(本文将试验),达夫设备的来源我就不说了,我们来分析一下. 达夫设备是考虑到我们一般用for或者while循环的时候, ...
- 高性能JavaScript 达夫设备
前言 在<高性能JavaScript>一书的第四章算法和流程控制中,提到了减少迭代次数加速程序的策略—达夫设备(Duff's device).达夫设备本身很好理解,但是其效果是否真的像书中 ...
- 达夫设备之js
最近阅读<高性能JavaScript>时,在书中的“达夫设备“ . 对此,有些感悟,同时有些疑问,希望看到的朋友,能帮忙解释下,在此先提前感谢了. 1. 先说自己的理解吧: ”达夫设备“的 ...
- 【转】Duff's Device
在看strcpy.memcpy等的实现发现用了内存对齐,每一个word拷贝一次的办法大大提高了实现效率,参加该blog(http://totoxian.iteye.com/blog/1220273). ...
- 读高性能JavaScript编程 第四章 Duff's Device
又要开始罗里吧嗦的 第四章 Summary 了. 这一次我尽量精简语言. 如果你认为 重复调用一个方法数次有点辣眼睛的话 比如: function test(i){ process(i++); pr ...
- Openck_Swift源代码分析——添加、删除设备时算法详细的实现过程
1 初始加入设备后.上传Object的详细流程 前几篇博客中,我们讲到环的基本原理即详细的实现过程,加入我们在初始创建Ring是执行例如以下几条命令: •swift-ring-builder obj ...
- OpenStack_Swift源代码分析——创建Ring及加入�设备源代码算法具体分析
1 创建Ring 代码具体分析 在OpenStack_Swift--Ring组织架构中我们具体分析了Ring的具体工作过程,以下就Ring中添加�设备,删除设备,已经又一次平衡的实现过程作具体的介绍. ...
- Nova: 虚机的块设备总结 [Nova Instance Block Device]
和物理机一样,虚拟机包括几个重要的部分:CPU.内存.磁盘设备.网络设备等.本文将简要总结虚机磁盘设备有关知识. 1. Nova boot CLI 中有关虚机块设备的几个参数 nova boot CL ...
随机推荐
- boost总结之any
boost中any库相对variant简单,any可以不限定类型,variant中对我们事先会定义好我们所需的类型,但是any无此限制,any的类型检测是在run time时. boost::an ...
- 数据结构:二级指针与Stack的数组实现
[简介] Stack,栈结构,即传统的LIFO,后进先出,常用的实现方法有数组法和链表法两种.如果看过我上一篇文章<数据结构:二级指针与不含表头的单链表>,一定会看到其中的关键在于,利用v ...
- bzoj 2707 [SDOI2012]走迷宫(SCC+高斯消元)
Description Morenan被困在了一个迷宫里.迷宫可以视为N个点M条边的有向图,其中Morenan处于起点S,迷宫的终点设为T.可惜的是,Morenan非常的脑小,他只会从一个点出发随机沿 ...
- cloudstack安装篇3-SELinux配置、NTP时间同步、配置ClouStack软件库
一.SELinux配置 为了让CloudStack正常工作,我们必须将SELinux设置为permissive.需要在当前系统运行状态下和启动后都能够生效,进行以下配置. 在系统运行状态下的将SELi ...
- mac使用初级
imac使用的是login shell,所有开启一个terminal的时候,不会运行.bashrc文件,而是运行.bash_profile文件,因此只需要中home目录新建一个.bash_profil ...
- javascript闭包问题
<script type="text/javascript"> window.onload = function(){ var name = "The Win ...
- 关于python文件转为exe文件
一.简介 py2exe是一个将python脚本转换成windows上的可独立执行的可执行程序(*.exe)的工具,这样,你就可以不用装python而在windows系统上运行这个可执行程序. py2e ...
- iOS 静态库和动态库
这两个东西都是编译好的二进制文件.就是用法不同而已.为什么要分为动态和静态两种库呢?先看下图:
- Redis_基本类型介绍和指令___2
1.hash Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象. Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿). ...
- CopyU!v2.2 增加对设备信息的识别
更新版本的CopyU!v2.2已经完成大部分功能的设计,主打升级功能“设备信息识别”已经基本完成,现在放上测试截图:
