达夫设备(Duff‘s Device)浅析

2024-01-23 20:20
文章标签 浅析 设备 device duff 达夫

本文主要是介绍达夫设备(Duff‘s Device)浅析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今天偶尔看到 Duff’s Device C语言代码 , 凭兴趣研究了一下;
这段代码的来历是这样的:
达夫设备(Duff’s Device)是一段著名的C语言代码,由Tom Duff在1983年编写,用于手动展开循环以优化数据的复制操作。它是一种与众不同的编程技巧,结合了C语言中的switch语句和do…while循环结构,达到循环展开(unrolling)的效果,从而提高程序的运行效率。

下面是一个标准的达夫设备的示例代码:

void duff_device(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);}
}

这段代码做的事情是将from指向的内存区域中的数据拷贝到to指向的内存区域中,拷贝的长度为count个字节。

解释一下代码的执行逻辑:

首先计算count除以8后向上取整的值给n,这将决定完整展开循环的次数。
然后通过count % 8获取剩余未处理的元素数量,作为switch语句的条件。
switch语句跳转到对应的case标签。这里的case标签作用是标记接下来需要执行的数据复制操作的起始点。
do…while循环开始执行,每次进入循环都执行8次数据复制操作,直到n减到0为止。当count不是8的倍数时,switch确保了从正确的地方开始复制。
达夫设备的核心优化思想是循环展开,通过减少循环迭代的次数来减少循环控制的开销,从而提高代码的执行效率。然而,这种技巧牺牲了代码的可读性,很容易导致代码维护上的困难,并且现代编译器的优化通常能够自动进行循环展开,所以它现在更多的是一个编程领域的趣闻,而不是推荐使用的代码实践。

读到这里 就自己动手实验了一下;
下面是我的实验代码


#include "test.h"void duff_device(char* to, char* from, int count)
{cout_time();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);}cout_time();
}int main()
{char s[100]="";char s1[100] = "hello world china";duff_device(s, s1, 17);std::cout << s <<std::endl;copy(s, s1, 17);std::cout << s << std::endl;
}void copy(char *to , char *from , int count)
{cout_time();for (int i = 0; i < count; i++) {*to++ = *from++;}cout_time();
}void cout_time()
{auto now = std::chrono::system_clock::now();//通过不同精度获取相差的毫秒数uint64_t dis_millseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count()- std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count() * 1000;time_t tt = std::chrono::system_clock::to_time_t(now);tm * time_tm = new tm();localtime_s(time_tm ,&tt);char strTime[25] = { 0 };sprintf_s(strTime, "%d-%02d-%02d %02d:%02d:%02d %03d", time_tm->tm_year + 1900,time_tm->tm_mon + 1, time_tm->tm_mday, time_tm->tm_hour,time_tm->tm_min, time_tm->tm_sec, (int)dis_millseconds);std::cout << strTime << std::endl;delete time_tm;
}

达夫代码运行了3毫秒,普通循环运行了不到1毫秒
达夫代码运行了3毫秒,普通循环运行了不到1毫秒 , 使用的ide是 windows visual studio
猜测现在的编译器早就优化了;

这篇关于达夫设备(Duff‘s Device)浅析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/637409

相关文章

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

浅析如何使用Swagger生成带权限控制的API文档

《浅析如何使用Swagger生成带权限控制的API文档》当涉及到权限控制时,如何生成既安全又详细的API文档就成了一个关键问题,所以这篇文章小编就来和大家好好聊聊如何用Swagger来生成带有... 目录准备工作配置 Swagger权限控制给 API 加上权限注解查看文档注意事项在咱们的开发工作里,API

浅析Rust多线程中如何安全的使用变量

《浅析Rust多线程中如何安全的使用变量》这篇文章主要为大家详细介绍了Rust如何在线程的闭包中安全的使用变量,包括共享变量和修改变量,文中的示例代码讲解详细,有需要的小伙伴可以参考下... 目录1. 向线程传递变量2. 多线程共享变量引用3. 多线程中修改变量4. 总结在Rust语言中,一个既引人入胜又可

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

如何编写Linux PCIe设备驱动器 之二

如何编写Linux PCIe设备驱动器 之二 功能(capability)集功能(capability)APIs通过pci_bus_read_config完成功能存取功能APIs参数pos常量值PCI功能结构 PCI功能IDMSI功能电源功率管理功能 功能(capability)集 功能(capability)APIs int pcie_capability_read_wo

(入门篇)JavaScript 网页设计案例浅析-简单的交互式图片轮播

网页设计已经成为了每个前端开发者的必备技能,而 JavaScript 作为前端三大基础之一,更是为网页赋予了互动性和动态效果。本篇文章将通过一个简单的 JavaScript 案例,带你了解网页设计中的一些常见技巧和技术原理。今天就说一说一个常见的图片轮播效果。相信大家在各类电商网站、个人博客或者展示页面中,都看到过这种轮播图。它的核心功能是展示多张图片,并且用户可以通过点击按钮,左右切换图片。

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《考虑燃料电池和电解槽虚拟惯量支撑的电力系统优化调度方法》

本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源程序擅长文章解读,论文与完整源程序,等方面的知识,电网论文源程序关注python

全英文地图/天地图和谷歌瓦片地图杂交/设备分布和轨迹回放/无需翻墙离线使用

一、前言说明 随着风云局势的剧烈变化,对我们搞软件开发的人员来说,影响也是越发明显,比如之前对美对欧的软件居多,现在慢慢的变成了对大鹅和中东以及非洲的居多,这两年明显问有没有俄语或者阿拉伯语的输入法的增多,这要是放在2019年以前,一年也遇不到一个人问这种需求场景的。 地图应用这块也是,之前的应用主要在国内,现在慢慢的多了一些外国的应用场景,这就遇到一个大问题,我们平时主要开发用的都是国内的地

驱动(RK3588S)第七课时:单节点设备树

目录 需求一、设备树的概念1、设备树的后缀名:2、设备树的语法格式3、设备树的属性(重要)4、设备树格式举例 二、设备树所用函数1、如何在内核层种获取设备树节点:2、从设备树上获取 gpio 口的属性3、获取节点上的属性只针对于字符串属性的4、函数读取 np 结点中的 propname 属性的值,并将读取到的 u32 类型的值保存在 out_value 指向的内存中,函数的返回值表示读取到的

Usb Audio Device Descriptor(10) Hid Device

对于 Standard Interface Descriptor, 当 bInterfaceClass=0x03时,即为HID设备。Standard Interface Descriptor如下 struct usb_standard_interface_descriptor{U8 bLength; /*Size of this descriptor in bytes*/U8 bDescrip