zer*_*0ne 3 c# f# ocaml functional-programming
我想写这个操作
Matrix.Multiply(source,target)
target.Add(offsets)
Run Code Online (Sandbox Code Playgroud)
在这种数学风格
target = Matrix * source + offsets;
Run Code Online (Sandbox Code Playgroud)
但是,我也很关心性能.(实际上,上面的操作将在紧密循环中运行.)我不想为每个矩阵向量乘法创建一个新向量,而为向量加法创建另一个新向量.
如何在C#或F#(或您知道的任何功能语言)中实现上述操作,以便可以实现样式和性能?
抱歉这个天真的问题.我确信这种愿望是如此根本.
gas*_*che 10
一种众所周知的技术,例如在高性能数值阵列的Repa库的核心,是在基本的"2D整数数组"结构之上定义一个更高级别的数据结构,它延迟了你的操作想要执行,以及最终执行这些操作的解释/规范化功能,应用它认为有利可图的任何优化.
具体来说,在您的示例中,我认为大多数当前的答案都错过了这个,您希望A * B + C不要重写
add(multiply(A,B), C)
Run Code Online (Sandbox Code Playgroud)
或者在OO风格中
A.multiply(B).add(C)
Run Code Online (Sandbox Code Playgroud)
但反而
multiply_and_add(A,B,C)
Run Code Online (Sandbox Code Playgroud)
其中multiply_and_add是specialez,低级操作,它同时执行两个操作并且更加优化.类似地,众所周知,对于任意矩阵A, B, C, D,A * B * C * D可以更有效地计算乘积,A * ((B * C) * D)而不是A * (B * (C * D)))取决于操作数维度.因此,纯粹的本地方法(在整数数组上表示每个操作)不起作用,您需要表达式 - 全局重写以获得最佳效率 - 正如C++中的hackish模板库所做的那样.
解决方案是从int array array精细数据类型转移到,例如:
type matrix =
| Raw of int array array
| Add of matrix * matrix
| Mult of matrix * matrix
Run Code Online (Sandbox Code Playgroud)
然后提供一个eval : matrix -> int array array函数,通过可能应用特定于域的优化来"解释"那些矩阵描述(实质上是矩阵运算的抽象语法树).一个天真的例子:
let rec eval = function
| Raw m -> m
| Add(Mult(a,b), c) | Add(c, Mult(a,b)) ->
multiply_and_add (eval a) (eval b) (eval c)
| Add (a, b) -> add (eval a) (eval b)
| Mult (a, b) -> mult (eval a) (eval b)
Run Code Online (Sandbox Code Playgroud)
然后,您可以定义您喜欢的语法糖,以使matrix构造函数更易于阅读.
module Matrix = struct
let (!) m = Raw m
let (+) a b = Add (a, b)
let (*) a b = Mult (a, b)
end
let ... = eval Matrix.(!A * !B + !C)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
255 次 |
| 最近记录: |