473,626 Members | 3,675 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

unexpected abstraction penalty in C++

class c {
int x;
public:
inline c() : x(0) {}
inline c(int i) { x = i; }
inline operator const int& () const { return x; }
inline operator int& () { return x; }
};
If I use objects of type `c' as if they were int's, I see about 1.5x
slow-down compared to using regular int's (timed using GCC-3.3.4 -O3). Is
it reasonable to expect modern compilers to optimize this, so that there is
no abstraction penalty?
Jul 23 '05 #1
8 1764
* alex goldman:
class c {
int x;
public:
inline c() : x(0) {}
inline c(int i) { x = i; }
inline operator const int& () const { return x; }
inline operator int& () { return x; }
};
'inline' is superflous here, because the functions are defined in-class
which makes the automatically 'inline'.

Second, 'inline' is at best only a hint.

To direct your compiler to optimize for speed, use your compiler's options
and/or non-standard language extensions.

If I use objects of type `c' as if they were int's, I see about 1.5x
slow-down compared to using regular int's (timed using GCC-3.3.4 -O3). Is
it reasonable to expect modern compilers to optimize this, so that there is
no abstraction penalty?


Don't know.

With the following main program:

int main( int nArgs, char* arg[] )
{
int forceCode = atoi( arg[1] );

int x = 0x1234 + forceCode;
x += 0x1111;
std::cout << x << std::endl;

c y = 0x1234 + forceCode;
y += 0x1111;
std::cout << y << std::endl;
}

Visual C++ 7.1, optimize for speed or full optimization, emits a
single instruction for the initialization of and addition to 'x',

; int x = 0x1234 + forceCode;
; x += 0x1111;
lea edx,[esi+2345h]

in contrast to two instruction for the code using your class, 'y',

; c y = 0x1234 + forceCode;
lea eax,[esi+1234h]
; y += 0x1111;
add eax,1111h

I don't understand why the compiler can see the optimization for 'x'
but not for 'y', having gone so far as to represent them identically.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #2
Alf P. Steinbach wrote:
* alex goldman:
class c {
int x;
public:
inline c() : x(0) {}
inline c(int i) { x = i; }
inline operator const int& () const { return x; }
inline operator int& () { return x; }
};

'inline' is superflous here, because the functions are defined in-class
which makes the automatically 'inline'.

Second, 'inline' is at best only a hint.

To direct your compiler to optimize for speed, use your compiler's options
and/or non-standard language extensions.
If I use objects of type `c' as if they were int's, I see about 1.5x
slow-down compared to using regular int's (timed using GCC-3.3.4 -O3). Is
it reasonable to expect modern compilers to optimize this, so that there is
no abstraction penalty?

Don't know.

With the following main program:

int main( int nArgs, char* arg[] )
{
int forceCode = atoi( arg[1] );

int x = 0x1234 + forceCode;
x += 0x1111;
std::cout << x << std::endl;

c y = 0x1234 + forceCode;
y += 0x1111;
std::cout << y << std::endl;
}

Visual C++ 7.1, optimize for speed or full optimization, emits a
single instruction for the initialization of and addition to 'x',

; int x = 0x1234 + forceCode;
; x += 0x1111;
lea edx,[esi+2345h]

in contrast to two instruction for the code using your class, 'y',

; c y = 0x1234 + forceCode;
lea eax,[esi+1234h]
; y += 0x1111;
add eax,1111h

I don't understand why the compiler can see the optimization for 'x'
but not for 'y', having gone so far as to represent them identically.


IMHO it's related to the point of time when the compiler's constant
folding kick in. I'd expect it to operate primarily on POD leaving out
objects (even though they might act the way the OP implements them). I
suppose this could impose overhead in the dataflow analysis which
probably won't pay off in most cases.

Cheers
Chris
Jul 23 '05 #3
alex goldman wrote:
class c {
int x;
public:
inline c() : x(0) {}
inline c(int i) { x = i; }
inline operator const int& () const { return x; }
inline operator int& () { return x; }
};
If I use objects of type `c' as if they were int's, I see about 1.5x
slow-down compared to using regular int's (timed using GCC-3.3.4 -O3). Is
it reasonable to expect modern compilers to optimize this, so that there is
no abstraction penalty?


Well you don't show us your code that actually uses the class, but there
are a few differences between
int [100];
and
c [100];

The first is that with an array of ints (or any POD) the default
initialization is either static or omitted. In your case,
a dynamic initialization always occurs.
Jul 23 '05 #4
On 2005-05-29, alex goldman <he***@spamm.er > wrote:
class c {
int x;
public:
inline c() : x(0) {}
inline c(int i) { x = i; }
inline operator const int& () const { return x; }
inline operator int& () { return x; }
};
If I use objects of type `c' as if they were int's, I see about 1.5x
slow-down compared to using regular int's (timed using GCC-3.3.4 -O3). Is
it reasonable to expect modern compilers to optimize this, so that there is
no abstraction penalty?


Does it make any difference if you change that to operator int() ?

Cheers,
--
Donovan Rebbechi
http://pegasus.rutgers.edu/~elflord/
Jul 23 '05 #5
Ron Natalie wrote:
In your case, a dynamic initialization always occurs.


That's a very good point. I removed the initialization just to be sure, but
it didn't make a difference for speed. It's still 2:3 for int vs the class.

Here's one of the benchmarks I ran:

#include <iostream>

class c {
int x;
public:
c() {}
c(int i) { x = i; }
operator const int& () const { return x; }
operator int& () { return x; }
};

#define LOOP1(i, n) for((i) = -(n); (i) <= (n); ++(i))
#define LOOP(i, j, k, n, a) \
a = 0; \
LOOP1(i, n) LOOP1(j, n) LOOP1(k, n) \
a += k + j; return a

int f_i(int n) {
int i, j, k, acc;
LOOP(i, j, k, n, acc);
}

int f_c(c n) {
c i, j, k, acc;
LOOP(i, j, k, n, acc);
}

int main() {
// std::cout << f_i(1000) << '\n';
std::cout << f_c(1000) << '\n';
}

Jul 23 '05 #6
Donovan Rebbechi wrote:

Does it make any difference if you change that to operator int() ?


I can't change the non-const operator to int (), but changing the const one
makes no difference.
Jul 23 '05 #7
alex goldman wrote:
Ron Natalie wrote:

In your case, a dynamic initialization always occurs.

That's a very good point. I removed the initialization just to be sure, but
it didn't make a difference for speed. It's still 2:3 for int vs the class.

You might try adding operator += and ++ to see what difference that
makes, or alternatively a operator=(int).
Jul 23 '05 #8
I wrote a more comprehensive test of various abstraction penalties in C++.
Here's what I get on P4 with GCC-3.3.4 -O3 (agressive optimization &
inlining):

$ time ./a.out

f_int(1000) : 9.240s
f_class1(1000) : 13.890s
f_class2(1000) : 19.510s
f_method(1000) : 13.850s
f_macro(1000) : 9.320s
f<int>(1000) : 9.240s
f<c>(1000) : 19.490s
f_get1(1000) : 13.850s
f_get2(1000) : 32.660s

real 2m21.092s
user 2m20.928s
sys 0m0.133s
Lessons learned:
* regular accessors (getters & setters) didn't help
* very minor things can confuse the optimizer (class1 vs class2)

I'm be curious to know how other CPUs/compilers do. Program text follows.

#include <iostream>
#include <ctime>
#include <iomanip>

using namespace std;

double time() { return double(clock()) / CLOCKS_PER_SEC; }

#define TIME_INC(e, res) { \
double t1 = time(); \
(res) += (e); \
double t2 = time(); \
cout << setw(15) << #e << " : " \
<< setw(7) << fixed << setprecision(3) \
<< t2 - t1 << "s" << endl; \
}

class c {
public:
int x;
c() {}
c(int i) : x(i) {}
operator const int& () const { return x; }
operator int& () { return x; }
const int& i() const { return x; }
int& i() { return x; }
int get() const { return x; }
void set(int i) { x = i; }
};

#define LOOP1(i, n) for((i) = -(n); (i) <= (n); ++(i))
#define LOOP(i, j, k, n, a) \
a = 0; \
LOOP1(i, n) LOOP1(j, n) LOOP1(k, n) \
a += k + j; return a

int f_int(int n) {
int i, j, k, acc;
LOOP(i, j, k, n, acc);
}

int f_class1(c n) {
c i, j, k, acc;
LOOP(i, j, k, n, acc);
}

// the return type is different from the above

c f_class2(c n) {
c i, j, k, acc;
LOOP(i, j, k, n, acc);
}

int f_method(c n) {
c i, j, k, acc;
LOOP(i.i(), j.i(), k.i(), n.i(), acc.i());
}

// very similar, but 1.5x faster!

#define I(e) (e).x
int f_macro(c n) {
c i, j, k, acc;
LOOP(I(i), I(j), I(k), I(n), I(acc));
}

template<class T>
T f(T n) {
T i, j, k, acc;
LOOP(i, j, k, n, acc);
}

int f_get1(c n) {
c i, j, k, acc = 0;
for(i.set(-n.get()); i.get() <= n.get(); i.set(i.get() + 1))
for(j.set(-n.get()); j.get() <= n.get(); j.set(j.get() + 1))
for(k.set(-n.get()); k.get() <= n.get(); k.set(k.get() + 1))
acc.set(acc.get () + k.get() + j.get());
return acc;
}

// the return type makes a big difference:

c f_get2(c n) {
c i, j, k, acc = 0;
for(i.set(-n.get()); i.get() <= n.get(); i.set(i.get() + 1))
for(j.set(-n.get()); j.get() <= n.get(); j.set(j.get() + 1))
for(k.set(-n.get()); k.get() <= n.get(); k.set(k.get() + 1))
acc.set(acc.get () + k.get() + j.get());
return acc;
}

#define TIME(e) TIME_INC(e(1000 ), dummy)

int main() {
int dummy = 0;
TIME(f_int);
TIME(f_class1)
TIME(f_class2)
TIME(f_method);
TIME(f_macro);
TIME(f<int>);
TIME(f<c>);
TIME(f_get1);
TIME(f_get2);
return dummy;
}

Jul 23 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
9239
by: Michael Andersson | last post by:
Hi! Does the use of exception handling induce a performance penalty during the execution of non exception handling code? Regards, /Michael
0
3084
by: Ed | last post by:
------=_NextPart_000_001D_01C34FCC.1D2B5E50 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable There seems to be a significant penalty imposed by the optimizer when = these 3 clauses are uses together. If we use the Full Text Search the penalty = is gone. However, the Full Text Search is not a very good option in my =
9
1872
by: A. Saksena | last post by:
Hi, Do anybody have an idea of the performance penalty while using exception handling (specially with g++) Abhishek
21
3404
by: ambika | last post by:
Hello, I have a very basic doubt. Why is C called a structured programming language??why structured? C++ is called a Object Oriented language 'cos it obeys the OOP's concepts..Why is C called a structured programming lang?? Thanks to all those who are gonna answer.. -ambika
6
1995
by: Mark Broadbent | last post by:
this might sound like an obvious question but I have found that usually these two evolve at the same time. One of the biggest reasons for creating the abstraction in the first place (in my opinion) is to create a reusable framework that can be applied to similar projects. However I have found that if an abstraction is created first during the development phase, when the implementation is occurring, the functionality or intended behaviour...
2
2262
by: Peter Bär | last post by:
A Question to the C#/.Net Gods of this forum: are there performance penalties when i compile (C#, FW1.1, ASP.NET, Studio2003) a central baseclass in a different assembly than all the derived classes? f.i. ive got a class dbobject i project "Basesupport", compiles to Basesupport.dll. From dbobject i derive about 100 classes, thy all are located in Project
1
1669
by: rickycornell | last post by:
Greetings All, On past projects in PHP4 I had always just written my own libraries to deal with database interaction. Somehow I was operating in the dark that there were all these database abstraction things available that made my work on the libraries I made from scratch a waste of time. So now I've started researching all these things that are available, and I have to say I am a little confused. It's a matter of understanding the...
2
7626
by: subramanian100in | last post by:
Is my following understanding correct ? Data abstraction means providing the interface - that is, the set of functions that can be called by the user of a class. Information hiding means mentioning the class members(functions, typedefs, data) under the access control labels : public, protected, private. Encapsulation means providing the implementation of class member
8
1822
by: Ivan S | last post by:
What are your recommendations for lightweight database abstraction library (Oracle/MySQL)? I prefer OOP. :) Tnx, Ivan.
0
8637
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8364
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8504
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7193
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5574
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4092
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4197
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2625
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1808
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.