gpt4 book ai didi

d - D 中的表达式模板

转载 作者:行者123 更新时间:2023-12-04 21:22:18 30 4
gpt4 key购买 nike

目标是达到与this C++ example相同的效果: 避免创建临时文件。我曾尝试将 C++ 示例翻译为 D,但没有成功。我也尝试过不同的方法。

import std.datetime : benchmark;
import std.stdio : writefln, writeln;

void bench(alias fun, string time = "msecs")(string msg, uint n = 1_000_000) {
auto b = benchmark!fun(n);
writefln(" %s: %s ms", msg, b[0].to!(time, int));
}

alias double Real;

struct Expression(string op, E1, E2) {
E1 _v1;
E2 _v2;
alias _v1 v1;
alias _v2 v2;

auto opIndex(size_t i) {
return mixin("v1[i]" ~ op ~ "v2[i]");
}

auto opBinary(string op, E)(auto ref E e) {
return Expression!(op, typeof(this), E)(this, e);
}
}

struct ExpVector {

Real[40] _data = void;
alias _data this;

this(Real datum) pure nothrow { _data = datum; }

auto opBinary(string op, T)(auto ref T other) {
return Expression!(op, typeof(this), T)(this, other);
}

void opAssign(E)(auto ref E exp) {
foreach(i, ref datum; _data)
datum = exp[i];
}
}

struct Vector {

Real[40] _data = void;
alias _data this;

this(Real datum) pure nothrow { _data = datum; }

auto opBinary(string op)(auto ref Vector other) {
Vector ret;
foreach(i, datum; _data)
ret[i] = mixin("datum" ~ op ~ "other[i]");
return ret;
}
}

void main() {

ExpVector e1 = ExpVector(1.5);
ExpVector e2 = ExpVector(7.3);
ExpVector ef;
void T1() {
ef = (e1 + e2) * (e1 + e2);
}
bench!T1(" vector operations using template expression");

Vector v1 = Vector(1.5);
Vector v2 = Vector(7.3);
Vector vf;
void T2() {
vf = (v1 + v2) * (v1 + v2);
}
bench!T2(" regular vector operations");

void T3() {
for(int i = 0; i < vf.length; ++i)
vf[i] = (v1[i] + v2[i]) * (v1[i] + v2[i]);
}
bench!T3(" what is expected if template expressions worked and temporaries were not created.");
}

表达式模板版本比非表达式模板版本慢。我期待表达式模板版本更快,更接近预期。那么我的表达式模板有什么问题呢?在 D 中做表达式模板的正确方法是什么?

最佳答案

在维基百科的 c++ 示例表达式中,表达式类包含对临时变量的引用,如果是表达式...

Vec a, b;
double c;
Vec result = ( a - b ) * c
...在分配给结果向量之前,我们在内存中有某种树:
a           b
\ /
\ /
\ /
VecDifference
\
\
\
VecScaled( has copy of 'c' embedded directly in object )
VecDifference 只保存对 a 和 b 的引用,而 VecScaled 保存对临时 VecDifference 的引用(根据 c++ 规则,它会一直存在,直到表达式结束)。最后,我们没有重复的初始数据,也没有不必要的计算(如果我们只使用向量的一些组件,而不是像简单分配给 Vec 那样使用所有组件)
在您的 struct Expression(string op, E1, E2) 中,初始和中间数据简单地复制到数据成员中,并且在前一个表达式的末尾,您将拥有
Expression!( "*", Expression!( "-", Vec, Vec ), double )
其中外部表达式将具有内部表达式("-", Vec, Vec ) 和双参数的副本,内部表达式将具有 a 和 b 向量的副本。因此,在一天结束时,您避免了临时 Vec 而是制作了 a 和 b 的 4 个副本(不计算对结果向量的最终分配)。
虽然,不知道在 D 中的这种情况下如何避免复制。也许指向 structres 的指针?
(顺便说一句,c++11 的自动类型推断和引用临时文件的表达式模板有不幸的交互,这可能会导致错误: http://lanzkron.wordpress.com/2011/02/21/inferring-too-much/)

关于d - D 中的表达式模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10132903/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com