Archived

This topic is now archived and is closed to further replies.

Jx

Choosing which lib automatically at runtime

Recommended Posts

Ok, so i''ve got my nice shiny vector and maths libraries, optimized for SSE and 3DNow!. All I want to be able to do now is say: Matrix3 tempMatrix = new Matrix3; and have it automatically return SSE or 3DNow! version. I would like not have to have if''s or cases to do this... Anyone got any solutions? I''ve thought of ways, but i don''t like them very much Hopefully someone can help....

Share this post


Link to post
Share on other sites
Well, you can use function pointers in C, or an abstract base class and virtual functions in C++. Both may incur considerable overhead if you''re looking to maximize performance.

You need to abstract at a higher level in the code, and construct two (or more) different functions, each using inlined MMx/SSE/3DNow code.

So instead of deciding which matrix multiplication you use, you decide which physics engine you''re going to use.

You can then either use macros and conditional compilation, or templates to produce the various flavors of the physics engine.

Share this post


Link to post
Share on other sites
You could just use different executables, using #ifdefs in your matrix functions to seperate the MMX, SSE, and 3DNow code. Then you compile it with the different defines, into GameMMX.exe, GameSSE.exe, and Game3DNow.exe, or whatever. Since no one's processor is going to change at run time, you can let the user choose which to download instead of cramming all three into one ZIP archive.

~CGameProgrammer( );



Edited by - CGameProgrammer on February 18, 2002 11:08:47 PM

Share this post


Link to post
Share on other sites
use the magic of polymorphism. though you will have to screw around with the new operator so that it creates the correct class, or call a special CreateMatrix() function so that you dont have to deal with overriding new. unfortunatly there is NO way to do this without some sort of conditional (if/switch) code somewhere.

Share this post


Link to post
Share on other sites

Hmm... runtime... dynamic... switching... Wait a minute!

Hey, isn''t that what DLL or shared libraries are for?!?

That''s right.

Make two DLL''s, one for SSE and one for 3DNow.

The DLL''s both "export" Matrix3 but are implemented
accordingly.

Call them MatrixSSE.dll and Matrix3DNow.dll.

Then your main program load the "Matrix.dll" which contains
the Matrix3 class. Simply copy the version of the DLL
you want to "Matrix.dll" and VOILA.

Alternatively, you can have a configuration that loads
the specific DLL explicitly.

But you get the idea.


Premature optimizations can only slow down your project even more.

Share this post


Link to post
Share on other sites
Thanks for all the suggestions guys. Some i''d already thought of, but i have some questions about each that were troubling me:

Magmai: Obviously i''d thought about abstract classes and virtual functions etc, but I want to be able to say

Matrix3 tempMatrix = new Matrix3;

and not

if AMD
Matrix3 tempMatrix = new AMDMatrix3;
else if INTEL
Matrix3 tempMatrix = new INTELMatrix3

if you see what i mean, and the abstract classes and virtual functions route seems to suggest i have to do it this way. This was what I was talking about when I said not using if''s ealier.

CGameProgrammer: Hehe, I hadn''t actually thought about just using different executables....

A person: Aha.. overloading new... have to look into that.. but surely if I want to do

Matrix3 tempMatrix = new Matrix3;

and have it decide then it won''t work still because you can''t instantiate an abstract class or interface? and so the compiler will complain?


tangentz: Hey, yeah! I could use DLLs, but then you can''t do what I wanted with a class in a dll... Don''t forget you create the class from within the dll, and free it in there too. So i''d have to have a function like CreateMatrix() and do this:

Matrix3 tempMatrix = CreateMatrix();

Plus, for dlls, I have to use virtual functions for which there is an overhead, plus there is overhead for calling a dll function... I know I can''t get around the virtual function overhead, but i''d like to minimize the cost because otherwise i''ll negate the benefits of the optimization....

Share this post


Link to post
Share on other sites
quote:
Original post by Jx
tangentz: Hey, yeah! I could use DLLs, but then you can''t do what I wanted with a class in a dll... Don''t forget you create the class from within the dll, and free it in there too. So i''d have to have a function like CreateMatrix() and do this:

Matrix3 tempMatrix = CreateMatrix();



Hmm... I see no reason why you''d have to do this. As long
as you "new" and "delete" the Matrix in the same place (app
or DLL), you''d be okay. So you don''t need CreateMatrix().
Since Matrix is so simple, I doubt there''s any trouble
making sure that is the case.

  
// Inside Matrix.dll

class DLLEXPORT Matrix
{
double m_Matirx[16];
// Plus the member functions

};
// end class



// Inside main application

Matrix *pMat = new Matrix;
// ...

delete pMat;

// Or simply,

Matrix Mat;


quote:
Original post by Jx
Plus, for dlls, I have to use virtual functions for which there is an overhead, plus there is overhead for calling a dll function... I know I can''t get around the virtual function overhead, but i''d like to minimize the cost because otherwise i''ll negate the benefits of the optimization....



Virtual functions? No, you don''t need them.

Hmm... once the DLL is loaded (which happens during app
initilizationg), it''s in memory. You call the functions
just like any other ordinary functions. There''s no calling
overhead.

So, I really don''t see why you can''t use DLL for your
problem.


Premature optimizations can only slow down your project even more.

Share this post


Link to post
Share on other sites
tangentz:
quote:

Virtual functions? No, you don't need them.



I don't understand how you think I can work this without virtual functions. What happens if i want this function somewhere else in my code:

RotateWorld(Matrix *TheMatrix);

Now if i have different .DLLs for the different processors - which is fine - i'm going to have to have some base Matrix class from which I derive AMDMatrix and INTELMatrix so I can have a generic function like that. In which case, in the generic base class i need something like:

    
class Matrix
{
public:

virtual ~Matrix( );

virtual mult( const Matrix& mat ) = 0;

...
etc
...
};



If i didn't have a generic base class, I would have to write 3 or more functions - one for each type of matrix right?

Also what happens if I don't want to link with the lib file for the dll. Every time i try and create a type of say AMDMatrix, i'll get an error from the linker.

quote:

Hmm... I see no reason why you'd have to do this. As long
as you "new" and "delete" the Matrix in the same place (app
or DLL), you'd be okay. So you don't need CreateMatrix().
Since Matrix is so simple, I doubt there's any trouble
making sure that is the case.



Ok - take a look at this:

Game Programming Gems 2 Section 1.4, Page 19:

quote:

There is one potential problem with declaring or allocating a class exported from a DLL in an application: it may confuse some memory-tracking programs and cause them to misreport memory allocations or deletions. To fix this problem, helper functions that allocate and destory instances of the exported class must be added to the DLL. All users of the exported class should call the allocation function to create and instance of it.



Also, looking at this article on GameDev
http://www.gamedev.net/reference/articles/article928.asp

they use the same approach and have two functions for allocation and deletion.



Edit: Added the bit about linker errors...

Edited by - Jx on February 19, 2002 11:51:13 AM

Share this post


Link to post
Share on other sites
quote:
Original post by Jx
I don't understand how you think I can work this without virtual functions. What happens if i want this function somewhere else in my code:



I thought I was pretty clear on how to do this, but I'll
try to explain again.

quote:
Original post by Jx
RotateWorld(Matrix *TheMatrix);

Now if i have different .DLLs for the different processors - which is fine - i'm going to have to have some base Matrix class from which I derive AMDMatrix and INTELMatrix so I can have a generic function like that. In which case, in the generic base class i need something like:



No, no, that's not it. Your AMDMatrix and INTELMatrix
are BOTH simply called "Matrix". In the AMD\Matrix.dll,
the Matrix class implements operations using AMD instructions
while in the Intel\Matrix.dll, the Matrix class implements
using Intel instructions. There is one and only one
class, namely, Matrix. It is a concrete class.

      
// In AMD\Matrix.dll

class DLLEXPORT Matrix
{
// Use AMD instructions

};
// end



// In Intel\Matrix.dll

class DLLEXPORT Matrix
{
// Use Intel instructions

};
// end



quote:
Original post by Jx
I don't understand how you think I can work this without virtual functions. What happens if i want this function somewhere else in my code:


         
RotateWorld(Matrix *TheMatrix);


Sure, why not? Matrix * simply means a pointer to a Matrix
object. So make one and pass it to RotateWorld().

quote:

If i didn't have a generic base class, I would have to write 3 or more functions - one for each type of matrix right?



Not sure what you mean. Surely you have Rotate, Translate,
Invert, Transpose... etc.. as public functions. That's
*the* interface for using the Matrix class. You can add
different private functions in AMD\Matrix and Intel\Matrix
to implement their specific functionalities.

quote:
Original post by Jx
Ok - take a look at this:

Game Programming Gems 2 Section 1.4, Page 19:

[quote]
There is one potential problem with declaring or allocating a class exported from a DLL in an application: it may confuse some memory-tracking programs and cause them to misreport memory allocations or deletions. To fix this problem, helper functions that allocate and destory instances of the exported class must be added to the DLL. All users of the exported class should call the allocation function to create and instance of it.



That's a fair warning for complex classes that allocate
their own memory/resource. But Matrix is so simple, there's
not much to worry about.

quote:
Original post by Jx
Also, looking at this article on GameDev
http://www.gamedev.net/reference/articles/article928.asp

they use the same approach and have two functions for allocation and deletion.



Again, fair warning for complex classes. For this specific
case of Matrix, there's nothing to worry about.

The quoted articles describe good techniques to avoid the
pitfalls. But that's only half of the whole picture. They
explain the HOW-TO. The other half is to understand WHEN-TO.
Apply techniques WHEN they make sense.

Premature optimizations can only slow down your project even more.

Edited by - tangentz on February 19, 2002 12:00:46 PM

Edited by - tangentz on February 19, 2002 12:02:33 PM

Share this post


Link to post
Share on other sites
Doesn''t that example fail when you want to link with the libs for the .dlls because Matrix is define twice?

Think so....

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Yes, it would fail if you tried to load 2 DLL''s with the same information at compile time. This is why they are dynamically loaded at run-time.. aka, after you''ve figured out which one you want to use on the system it''s running on. This is also the reason they can have the EXACT same names for classes/variables/etc.. because only ONE gets used at runtime, and neither is refrenced at compile time.

Billy - BillyB@mrsnj.com

Share this post


Link to post
Share on other sites
But with the method i suggest, you can do either - link with the libs, or load dynamically at runtime.

Hmm... need a second opinion...

Thanks for all the input though tagentz - it''s helpfull to have someone to bounce your ideas off even if we''re getting our wires crossed



Magmai Kai Holmlor:

quote:

You need to abstract at a higher level in the code, and construct two (or more) different functions, each using inlined MMx/SSE/3DNow code.



So Magmai, you don''t thinks it''s worthwhile optimizing just the matrix and vector libraries?

quote:

So instead of deciding which matrix multiplication you use, you decide which physics engine you''re going to use.

You can then either use macros and conditional compilation, or templates to produce the various flavors of the physics engine.



Any examples?

Share this post


Link to post
Share on other sites
One other thing - with the method tangentz suggested, you HAVE to link with the lib otherwise the linker will complain. So if I can''t link with both libs, but I have to link with one then how will it work?

Share this post


Link to post
Share on other sites
if you go the dll route (MUCH better route imho). here is how you can do things (and load multiple dlls at the same time.

the trick is not to use an abstract class, but an empty base class which defines the funtions for the most genric method possible.

you create a simple template class. this class MUST contain all functions that all the classes will require. simply have all functions/operators "return 0" (if needed) so thay have a function body. then you base ALL your cpu specifc version on that class. you DO NOT link to the lib of the dll in exe. instead use LoadLibrary() and get the functions using GetFunctionByName() (i think thats the call). now in your exe make a class (if you wish) that does the following:

1. checks the cpu for which dll to use.
2. loads the correct dll, or the generic if none apply.
3. you make all requests for new matrices by using a create function instead of the new operator. this create function is exported by the dll and handles the new for you. you will also need to have a delete function in the dll which will handle the freeing (since things created by dlls should be freed by the dll).

this is how polymorrohism and dlls work. now you can add as many different versions of dlls WITHOUT recompiling the original exe. i use this method in my plugin system for loading images. i create a "house" which holds all the codecs at load time. and the house based on the codecs response to the filename passed will use the approiate class from the correct dll to load the file into a genric image buffer class (width, height, pointer to data, color dpeth) for me to manipulate. this makes everything abbstracted very nicly.

again you NEVER link with the dll libs. you MUST do things dynamicly and load the libraries at runtime yourself (and free them using FreeLibrary). check msdn, its ctaully quite trivial once you wrap it all in a class.

Share this post


Link to post
Share on other sites
That''s the way i was thinking of doing it - or at least something similar. But tangentz method was different. I was just wondering which was better.

Share this post


Link to post
Share on other sites