我正在学习Oleg的教程“将抽象与高性能相协调:一种MetaOCaml方法”。一个练习(练习23)要求让插入来绑定数组索引访问到局部变量。问题的函数是vmult_ca,它生成用于乘法复数数组的代码:
let vmult_ca :
(float_complex array -> float_complex array -> float_complex array -> unit)
code =
.<fun vout v1 v2 ->
let n = Array.length vout in
(* vector representations *)
.~(let vout = OVec (.<n>., fun i v ->
.<vout.(.~i) <- .~(of_code_complex v)>.) in
let v1 = Vec (.<n>., fun i ->
of_complex_code .<v1.(.~i)>.) in
let v2 = Vec (.<n>., fun i ->
of_complex_code .<v2.(.~i)>.) in
let module V = VMULT(FloatCodeComplex)(VecDyn) in
V.vmult vout v1 v2)
>.
;;其中vout是存储结果的输出向量。Vec (n, fun i -> v)是一个抽象向量,其中n是长度,fun i -> v将每个索引映射到一个值。OVec (n, fun i v -> body)是一个抽象的“输出向量”,其中n是长度,fun i v -> body在每个索引i上运行,并在i上运行相关的输出元素v。of_complex_code将complex code值转换为code complex值,例如.<{real=1.0, imag=0.0}>.转换为{real=.<1.0>., imag=.<0.0>.}。模块VMULT定义(点向)向量乘法(详见代码这里 )。
运行时,vmult_ca生成以下代码:
val vmult_ca :
(float_complex array -> float_complex array -> float_complex array -> unit)
code = .<
fun vout_4 ->
fun v1_5 ->
fun v2_6 ->
let n_7 = Array.length vout_4 in
for i_8 = 0 to n_7 - 1 do
vout_4.(i_8) <-
{
Cmplx.im =
(((v1_5.(i_8)).Cmplx.re *. (v2_6.(i_8)).Cmplx.im) +.
((v1_5.(i_8)).Cmplx.im *. (v2_6.(i_8)).Cmplx.re));
Cmplx.re =
(((v1_5.(i_8)).Cmplx.re *. (v2_6.(i_8)).Cmplx.re) -.
((v1_5.(i_8)).Cmplx.im *. (v2_6.(i_8)).Cmplx.im))
}
done>.注:v1_5.(i_8)被重复4次。挑战是在vmult_ca中的某个位置插入一个v1_5.(i_8),以便将v1_5.(i_8)绑定到局部变量以避免重复。我只需在genlet上调用.<v1.(~i)>.就可以“欺骗”,但我不知道在哪里插入没有genlet的let;任何提示都将不胜感激。
发布于 2020-03-26 20:50:48
让插入是误码率中的原始运算,它自动地将传递的代码绑定到新生成的变量上.
下面是一个工作示例,假设您有返回数组元素的正方形的代码,
let power_elt xs i = xs.(i) * xs.(i)我们希望生成一个只有一个数组访问权限的优化代码。
let power_elt xs i = let x = xs.(i) in x*x在MetaOCaml风格中,我们可以使用genlet
let power_elt xs i =
let x = genlet .<xs.(i)>. in
.<.~x * .~x>.生成的代码
let t = power_elt [|1;2;3|] 1;;将会是
val t : int code = .<let lv_8 = Stdlib.Array.get (* CSP xs *) 1 in lv_8 * lv_8>.https://stackoverflow.com/questions/60825487
复制相似问题