以下是 Mastering Dyalog APL 书中关于内部积的章节的摘录:
HMS is a variable which contains duration in Hours, Minutes, and Seconds: HMS ← 3 44 29 Chapter J – Operators 397
We would like to convert it into seconds. We shall see 3 methods just now, and a 4th
method
will be given in another chapter.
A horrible solution (3600×HMS[1]) + (60×HMS[2]) + HMS[3]
A good APL solution +/ 3600 60 1 × HMS
An excellent solution with Inner Product 3600 60 1 +.× HMS
然后它说第二个和第三个解决方案在键入的字符数 和性能 方面是等效的。
据我了解,APL 程序员一般应该尽可能多地使用内积和外积。那是对的吗?
你能举一个例子,当使用内积会导致性能提升吗?当我使用内积(在较低级别)时到底会发生什么?下面介绍的第一个解决方案是否很糟糕,因为它没有以正确的方式使用 APL 语法还是实际上性能更差?
我知道有几个问题,但我想问的是 内部/外部产品如何工作以及 APL 程序员何时应该使用它们 。
最佳答案
这真的取决于 APL 程序员和手头的任务,但如果有什么能让 APL 代码更简洁和高效,我不明白为什么程序员不会选择它。
在这种特殊情况下,60⊥HMS
比内积更简洁、更高效。
正如在面向数组的编程中一样,性能提升是通过一次性完成的。
大多数 APL 函数都是隐式循环——它们的实现使用一个计数器、一个限制和一个增量步。
你的代码越短越好,因为它不仅更容易记住,而且效率也更高,因为解释器必须对数据进行更少的传递。
一些实现进行循环融合以试图减少这种开销。
有些具有习语识别功能——某些波浪线组合在解释器中是特殊情况。一次性完成还允许解释器进行巧妙的优化,例如使用 SSE 指令集或 GPU。
回到内积,让我们以 A f.g B
为例,其中 A
和 B
是向量,看看 f
和 g
是如何应用的(在 Dyalog 中):
f←{⎕←(⍕⍺),' f ',⍕⍵ ⋄ ⍺+⍵}
g←{⎕←(⍕⍺),' g ',⍕⍵ ⋄ ⍺×⍵}
0 1 2 3 4 f.g 5 6 7 8 9
4 g 9
3 g 8
24 f 36
2 g 7
14 f 60
1 g 6
6 f 74
0 g 5
0 f 80
80
从上面可以看出,对
f
和 g
的调用是交错的。解释器同时处理 f
并减少 g
,一次性完成,避免创建临时数组,就像 f/ A g B
所做的那样。另一个例子:http://archive.vector.org.uk/art10500200
您可以自己测试不同解决方案的性能,看看哪一个最有效:
)copy dfns.dws cmpx
⍝ or: ")copy dfns cmpx" if you are using Windows
HMS ← 3 44 29
cmpx '(3600×HMS[1]) + (60×HMS[2]) + HMS[3]' '+/ 3600 60 1 × HMS' '3600 60 1 +.× HMS' '60⊥HMS'
(3600×HMS[1]) + (60×HMS[2]) + HMS[3] → 2.7E¯6 | 0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
+/ 3600 60 1 × HMS → 9.3E¯7 | -66% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
3600 60 1 +.× HMS → 8.9E¯7 | -68% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
60⊥HMS → 4.8E¯7 | -83% ⎕⎕⎕⎕⎕⎕⎕
关于matrix - 了解 APL 的内积,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24141989/