【发布时间】:2016-01-25 15:34:57
【问题描述】:
我们知道Duff's device 使用交错的结构切换和循环,例如:
send(to, from, count)
register short *to, *from;
register count;
{
register 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);
}
}
现在,在 Swift 2.1 中,switch-case control flows 并没有像我们在 Swift 文档中看到的那样隐含失败:
没有隐式失败
与 C 和 Objective-C 中的 switch 语句相比,switch Swift 中的语句不会落在每个 case 的底部,并且 默认进入下一个。相反,整个 switch 语句 一旦第一个匹配的 switch case 完成它的执行 完成,不需要显式的 break 语句。这使得 switch 语句比 C 语言更安全、更容易使用,并且避免了 错误地执行了多个 switch case。
现在,鉴于在 Swift 中有一个 fallthrough 子句显式地具有 fallthrough 副作用:
穿越
Swift 中的 Switch 语句不会落在每个 case 的底部 并进入下一个。相反,整个 switch 语句完成 它在第一个匹配案例完成后立即执行。经过 相反,C 要求您在 每个开关盒的末端,以防止跌落。避免违约 fallthrough 意味着 Swift switch 语句更加简洁 并且比它们在 C 中的对应物可预测,因此它们避免了 错误地执行了多个 switch case。
这很像:
let integerToDescribe = 5
var description = "The number \(integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
description += " a prime number, and also"
fallthrough
default:
description += " an integer."
}
print(description)
// prints "The number 5 is a prime number, and also an integer."
考虑到 Wikipedia 提醒我们,这些设备来自问题
A straightforward code to copy items from an array to a memory-mapped output register might look like this:
do { /* count > 0 assumed */
*to = *from++; /* "to" pointer is NOT incremented, see explanation below */
} while(--count > 0);
Duff 的设备在 Swift 中的具体实现是什么?
这只是一个语言和编码问题,并不打算应用于真正的 Swift 应用程序。
【问题讨论】:
-
呃...这是 1983 年的优化。像高速缓存和分支预测这样的东西几乎没有发明,更不用说高度优化的
memcpy实现了。为什么你会根据 1980 年代的算法优化代码?为什么你认为这些东西在今天仍然适用? -
@Lundin:我没有看到有人谈论任何“优化”。我认为这个问题非常清楚,它与优化甚至任何现实生活中的编码场景无关。这是一个关于可用语言结构灵活性的抽象问题。
-
Duff 的 Device 依赖于 C 的
switch语句的两个特性: (1) 默认情况下执行通过case和default标签; (2)switch的case和default标签可以出现在嵌套控制结构中(if/else、while、do/while或for)。即使您可以使用fallthrough指令在 Swift 中执行 (1),我假设它不支持 (2)。 -
@Lundin:它复制到硬件寄存器这一事实使其与 memcpy 截然不同。除了循环展开(这是 Duff 的设备的全部内容)之外,另一个常见的 memcpy 优化是一次移动更大的数据单元,如果您的目标是 1 字节硬件寄存器,您就无法做到这一点。至于除法,它是一个整数除法和一个循环外的模数。由于分母是 2 的幂,大多数编译器会将它们转换为位移位和掩码——这在微控制器上不是问题。达夫的设备今天完美无缺。
-
当然,Swift 不会允许编译这种代码。事实上,Duff's device 本质上是一个不应该编译的疏忽(意外)。在某些时候,有人发现它可以用于循环展开优化,因此最终保留了语言中的漏洞。今天,这几乎无关紧要,因为编译器要先进得多,并且所需的优化也非常不同,因为架构在多核、缓存、管道等方面发生了很大变化。同样在现代语言中,你并不像实际的 CPU 指令那样接近.
标签: c swift switch-statement fall-through duffs-device