Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!radar!cadillac!vaughan@mcc.com From: vaughan@mcc.com (Paul Vaughan) Newsgroups: comp.lang.c++ Subject: Re: why is this program slow? Message-ID: <14536@cadillac.CAD.MCC.COM> Date: 9 Jan 91 16:41:21 GMT References: <1991Jan9.002244.23398@news.cs.indiana.edu> Sender: news@cadillac.CAD.MCC.COM Reply-To: vaughan@mcc.com (Paul Vaughan) Organization: MCC VLSI CAD Program Lines: 196 In-reply-to: shirley@iuvax.cs.indiana.edu (peter shirley) From: shirley@iuvax.cs.indiana.edu (peter shirley) Newsgroups: comp.lang.c++ Date: 9 Jan 91 05:22:13 GMT Organization: Computer Science, Indiana University Lines: 115 I have a C++ program that takes about 170% as long as a similar C program. I've run it on a vax and a sun with and without big-O. I've inlined everything I can, and I don't understand the slowdown. Could someone enlighten me? (yes, I looked at the C code generated by CC, and am too dumb to understand it). The answer is that the C++ version has to construct and copy a temporary vector. Here are some timings I made that show this effect by noting the difference between using your version and using a vector::operator+= that avoids the copy. These timings were all on a SUN4. Note the user time. Using a = a + b [1.95]sunspot) g++-1.90.04 -O -o trash trash.cc -lg++ trash.cc: In function class vector operator + (class vector &, class vector &): trash.cc:62: warning: bitwise copy: `vector' defines operator=() [1.96]sunspot) /bin/time trash (1e+06, 2e+06, 4e+06) 32.1 real 10.0 user 0.2 sys (Ignore the warning from g++, it's inappropriate) Using a += b; [1.93]sunspot) g++-1.90.04 -O -o trash trash.cc -lg++ trash.cc: In function class vector operator + (class vector &, class vector &): trash.cc:62: warning: bitwise copy: `vector' defines operator=() [1.94]sunspot) /bin/time trash (1e+06, 2e+06, 4e+06) 13.3 real 5.2 user 0.0 sys Using a = a + b; [1.97]sunspot) CC -O -o trash trash.cc CC trash.cc: cc -o /d2/prism/prism/src/sim/src/trash -I/net/sunspot/usr/cadsw/CC/sun4/incl -O trash.c -L/net/sunspot/usr/cadsw/CC/sun4/ -lC [1.98]sunspot) /bin/time trash (1e+06, 2e+06, 4e+06) 23.0 real 8.2 user 0.1 sys Using a += b; [1.99]sunspot) CC -O -o trash trash.cc CC trash.cc: cc -o /d2/prism/prism/src/sim/src/trash -I/net/sunspot/usr/cadsw/CC/sun4/incl -O trash.c -L/net/sunspot/usr/cadsw/CC/sun4/ -lC [1.100]sunspot) /bin/time trash (1e+06, 2e+06, 4e+06) 8.8 real 3.4 user 0.1 sys Here is the vector::operator+= that I added: inline vector& vector::operator+=(vector& v) { data[0] += v.data[0]; data[1] += v.data[1]; data[2] += v.data[2]; return *this; } The concept of a named return value that a compiler could use to optimize away this sort of temporary copy has been proposed. I think it was Doug Lea who came up with that, but I'm not sure. I don't know the status of that suggestion. Finally, here is the original code. The C, then C++ code follow. Thanks, Pete Shirley shirley@cs.indiana.edu **************** begin C code ********************* #include "stdio.h" main() { int i; double a[3], b[3]; a[0] = a[1] = a[2] = 0.0; b[0] = 1.0; b[1] = 2.0; b[2] = 4.0; for ( i = 0; i < 1000000; i++) { a[0] = a[0] + b[0]; a[1] = a[1] + b[1]; a[2] = a[2] + b[2]; } fprintf(stderr, "%lf %lf %lf\n", a[0], a[1], a[2]); } ************* end C code ******************* ************** begin C++ code ********************* #include #include class vector { protected: double data[3]; public: vector(); vector(double, double, double); void set(double, double, double); void operator=(vector&); friend ostream& operator<<(ostream&, vector&); friend vector operator+(vector&, vector&); }; inline vector::vector() { } inline vector::vector(double a, double b, double c) { data[0] = a; data[1] = b; data[2] = c; } inline void vector::set(double a, double b, double c) { data[0] = a; data[1] = b; data[2] = c; } inline void vector::operator=(vector& v) { data[0] = v.data[0]; data[1] = v.data[1]; data[2] = v.data[2]; } inline vector operator+(vector& u, vector& v) { vector temp; temp.data[0] = u.data[0] + v.data[0]; temp.data[1] = u.data[1] + v.data[1]; temp.data[2] = u.data[2] + v.data[2]; return temp; } inline ostream& operator<<(ostream& s, vector& t) { return s << "(" << t.data[0] << ", "<< t.data[1] <<", " << t.data[2] <<")"; } main() { vector a(0.0, 0.0, 0.0); vector b(1.0, 2.0, 4.0); for (int i = 0; i < 1000000; i++) a = a + b; cerr << a << "\n"; } ************** end C++ code *********************** -- Paul Vaughan, MCC CAD Program | ARPA: vaughan@mcc.com | Phone: [512] 338-3639 Box 200195, Austin, TX 78720 | UUCP: ...!cs.utexas.edu!milano!cadillac!vaughan ---------------------------------------------------------------------------------- I spent from $3 to $10 today to pay interest on the national debt. How about you? ---------------------------------------------------------------------------------- Paul Vaughan, MCC CAD Program | ARPA: vaughan@mcc.com | Phone: [512] 338-3639 Box 200195, Austin, TX 78720 | UUCP: ...!cs.utexas.edu!milano!cadillac!vaughan ----------------------------------------------------------------------------------