Sign in to follow this  
Lyve

Troubles optimizing some code:

Recommended Posts

Lyve    116
Hello members, Is there a way to get a pointer to a member function of a class in C++? If not, why? I'm just sitting here, trying to optimize some code where a lot of accesses of the form [y*width+x] are made into an array. You can eliminate the multiplication when you replace them with shift operations. For a width of 640 that would be:
inline unsigned int shift640( unsigned int y )  { return (y<<9) + (y<<7); }

You can access your array now by using [shift640(y)+x] That is working well and is fast. Now I'm having the problem, I've got a image class where a function should be able to be used with any image size. So I thought I could store a pointer to the appropriate shift function, then in the loop just call the function in the pointer that I stored before. Something like that:
	// find a suitable shift function
	unsigned int (*funcShift)(unsigned int y);

	switch( width )
	{
	case 1920:	funcShift = blur_shift1920;		break;
	case 1600:	funcShift = blur_shift1600;		break;
	case 1280:	funcShift = blur_shift1280;		break;
	case 1200:	funcShift = blur_shift1200;		break;
	case 1152:	funcShift = blur_shift1152;		break;
	case 1080:	funcShift = blur_shift1080;		break;
	case 1024:	funcShift = blur_shift1024;		break;
	case 864:	funcShift = blur_shift864;		break;
	case 800:	funcShift = blur_shift800;		break;
	case 720:	funcShift = blur_shift720;		break;
	case 640:	funcShift = blur_shift640;		break;
	case 576:	funcShift = blur_shift576;		break;
	case 512:	funcShift = blur_shift512;		break;
	case 384:	funcShift = blur_shift384;		break;
	case 320:	funcShift = blur_shift320;		break;
	case 256:	funcShift = blur_shift256;		break;
	case 240:	funcShift = blur_shift240;		break;
	default:	funcShift = blur_shiftNoShift;	break;
	}

That's working well as long as the shift functions are not member functions of the image class itself. But they have to be, because the default function blur_shiftNoShift() needs to know the width of the image because the function returns just "y * m_width".
unsigned int blur_shiftNoShift( unsigned int y ){ return y * width; }

However, my compiler won't let me do that. And that's odd. Any hints? Thanks, Nils

Share this post


Link to post
Share on other sites
snk_kid    1312
Quote:
Original post by Lyve
However, my compiler won't let me do that. And that's odd. Any hints?


Pointer to free-function != Pointer to member function

and in order to work with pointer to member functions you need an instance of the type in question.

[Edited by - snk_kid on November 23, 2004 5:36:43 AM]

Share this post


Link to post
Share on other sites
MaulingMonkey    1730
Note that because you're accessing the function via a function pointer (which is a call you can't inline), you will likely kill any speed benifit you gained from using shifts instead of a generic multiplication in the first place.

Also note that you're probably prematurely optimizing, which is a BAD THING (tm). Code this optimized does not really belong in a userspace program. In drivers, yes.

All that said:

For the purpouses of explaining the syntax of C++, and how to make this example work (even if it's a bad idea to implement):

I'd suggest making the shift* functions static (prefered here, since it dosn't need to access any of the member functions). Example:

static unsigned int shift640( unsigned int y ) { return (y<<9) + (y<<7); }

(Note the lack of the inline keyword - it makes no sense in this context, since you're using a function pointer.)

Member functions of C++ classes are special, in that they work with an instance of the class - in other words they need a this pointer, which is used implicitly whenever you accesses a member of the class (other functions that use the this pointer, or directly through any non-static variables).

The use of the "static" keyword for a member function means you can't use the this pointer, or any non-static variables.

The use of the "static" keyword for a member variable means there's only one instance of that variable for the entire type. You'll also have to provide an instansiation of that variable in one of your compile units.

In cases where a "this" pointer is needed for the function to work, you need a different syntax. Example:


class MyClass
{
int my_number;
public:
MyClass( int my_number )
: my_number(my_number)
{
}
void print_number( void )
{
cout << "My number: " << my_number << endl;
}
void print_5_times_number( void )
{
cout << "My number times 5: " << (my_number * 5) << endl;
}
};

void (MyClass::*function)( void ); //Declares the pointer
function = MyClass::print_number; //Sets the function called

MyClass my_class_5 ( 5);
MyClass my_class_10 (10);

my_class_5.*function(); //Prints 5
my_class_10.*function(); //Prints 10

function = MyClass::print_5_times_number;

my_class_5.*function(); //Prints 25
my_class_10.*function(); //Prints 50

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Additionally, what you are proposing (an indirect function call) will be SLOWER on modern CPU:s than actually doing the multiplication in the normal way.

Share this post


Link to post
Share on other sites
civguy    308
What I did in an old game was that I roofed the map width to closest power of 2. I.e. 500 => 512, 600 => 1024. Then used just one shift to access a row. This way you won't need separate functions for different image sizes, just one variable that tells how much to shift. But was it really worth it? Dunno, back then I didn't really profile...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this