Expression templates are used in C ++ template to support both the elegance and efficiency of Array Operations. metaprogramming is mainly applicable to arrays with small sizes, expression templates applies to the runtime operations of neutral and large arrays. But in fact, after my tests, meta-programming and expression templates are not as amazing as they are in the book. Maybe I didn't implement them well. Below, I will test expression
Templates.
To support the following operations:
Array<double> x(1000), y(1000);...x = 1.2 * x + x * y;
Array array must overload operator + and operator * and return a temporary array object. The above code has two defects:
1. Three temporary array objects will be generated, each of which is 1000 in size;
2. Read 6000 Double Variables and write 4000 double variables;
In terms of performance, the following code has good performance, but it loses the elegance of the Code.
for ( int idx = 0; i < x.size(); ++ i ) { x[idx] = 1.2*x[idx] + x[idx]*y[idx];}
The expression template is used to support this simple code writing and maintain the efficiency of Array Operations. Both the source code and test code are on the resource. The following is the test code:
int CNT = 10000000;//test sarrayInteger i3(3), i4(4), i10(10);SArray<Integer> a(CNT), b(CNT);SArray<Integer> const& af = a;SArray<Integer> const& bf = b;clock_t s, e;s = clock();for ( int i = 0; i < CNT; ++ i )a[i] = i3 * af[i] + bf[i]*af[i] + af[i]*i4 + bf[i]*i10;e = clock();cout << "for time: " << e-s << "ms " << " addcnt: " << int_addcnt << " mulcnt: " << int_mulcnt << " readcnt: " << SArray<Integer>::readcnt<< " writecnt: " << SArray<Integer>::writecnt<< " temperary: " << SArray<Integer>::sarraycnt << endl;int_addcnt = 0;int_mulcnt = 0;SArray<Integer>::sarraycnt = 0;SArray<Integer>::readcnt = 0;SArray<Integer>::writecnt = 0;SArray<Integer> inta(CNT), intb(CNT);s = clock();inta = i3*inta + intb*inta + inta*i4 + intb*i10;e = clock();cout << "SArray time: " << e-s << "ms " << " addcnt: " << int_addcnt << " mulcnt: " << int_mulcnt << " readcnt: " << SArray<Integer>::readcnt<< " writecnt: " << SArray<Integer>::writecnt<< " temperary: " << SArray<Integer>::sarraycnt << endl;int_addcnt = 0;int_mulcnt = 0;SArray<Integer>::sarraycnt = 0;SArray<Integer>::readcnt = 0;SArray<Integer>::writecnt = 0;Array<Integer, SArray<Integer> > ia(CNT), ib(CNT);s = clock();ia = i3*ia + ib*ia + ia*i4 + ib*i10;e = clock();cout << "Array time: " << e-s << "ms " << " addcnt: " << int_addcnt << " mulcnt: " << int_mulcnt << " readcnt: " << SArray<Integer>::readcnt<< " writecnt: " << SArray<Integer>::writecnt<< " temperary: " << SArray<Integer>::sarraycnt << endl;
Ubuntu11.04 running result:
For time: 900000 Ms addcnt: 30000000 mulcnt: 40000000 readcnt: 50000000 writecnt: 10000000 temperary: 2
Sarray time: 3360000 Ms addcnt: 30000000 mulcnt: 40000000 readcnt: 110000000 writecnt: 70000000 temperary: 9
Array time: 14710000 Ms addcnt: 30000000 mulcnt: 40000000 readcnt: 50000000 writecnt: 10000000 temperary: 2
Win7 results:
For time: 6637 Ms addcnt: 30000000 mulcnt: 40000000 readcnt: 50000000 writecnt: 10000000
Temperary: 2
Sarray time: 31399 Ms addcnt: 30000000 mulcnt: 40000000 readcnt: 110000000 writecnt:
70000000 temperary: 16
Array time: 174527 Ms addcnt: 30000000 mulcnt: 40000000 readcnt: 50000000 writecnt:
10000000 temperary: 2
As you can see, the number of reads and writes in array is much smaller than that in sarray, and array has no temporary variables, but the final result is a big drop, array is more than twice slower than sarray! I guess the array uses expression templates. Although it avoids the generation of temporary arrays and significantly reduces the access to variables, it brings a problem: too many function calls increase the running time. I don't know if my analysis is justified. I hope you can give me some advice.
The next question is, in what scenarios can expression templates play the best role? Isn't the array of expression 10000000 large enough? 360 degrees naked in the ice and snow beg for the truth.