L'obiettivo è ottenere lo stesso effetto di this C++ example: evitare di creare provvisori. Ho provato a tradurre l'esempio C++ in D senza successo. Ho anche provato approcci diversi.in 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.");
}
La versione del modello di espressione è più lenta della versione del modello di non-espressione. Mi aspettavo che la versione del modello di espressione fosse molto più veloce e vicina a quanto previsto. Allora, cosa c'è di sbagliato con i miei modelli di espressione? Qual è il modo corretto di fare modello di espressione in D?
Beh, senza nemmeno considerare che cosa fa il codice, vorrei sottolineare che si avrebbe bisogno di compilare il codice su un compilatore che condivide un back-end con il compilatore C++ per poter realmente confrontare il linguaggio piuttosto che l'implementazione del compilatore. Se usi gdc per la roba D e gcc per la roba C++, otterrai un confronto molto migliore della lingua stessa. Il codice D potrebbe essere più lento semplicemente perché il backend di dmd non si ottimizza così come fa gcc. Potrebbe esserci molto di più, ma confrontare dmd vs gcc potrebbe facilmente essere comparativo con gli ottimizzatori dei due compilatori. –
Penso che tu abbia frainteso quello che ho detto. Il codice che ho postato è più del doppio della versione senza template di espressioni, cioè una normale struct 'Vector' che implementa la funzione membro' opBinary', con entrambe le versioni compilate con DMD. Non sto confrontandolo con il codice C++ in Wikipedia. – Arlen
Quindi dovresti postare entrambe le versioni. È difficile confrontare qualcosa con qualcos'altro quando hai solo uno dei due. –