On Mar 24, 2006, at 10:10 AM, IOhannes m zmölnig wrote:
Modified Files: GemSIMD.h Added Files: GemSIMD.cpp Log Message: implemented a small static class GemSIMD which is used to query the SIMD-capabilities of the current CPUs: this should bring us away from (not) using SIMD via preprocessors.
...this seems like a good thing (I'd like to also add a runtime check for g4 and g5 seperation...), but it's not working on this end atm...
...I'm a bit confused as to how it's supposed to work: "m_simd" is a static variable in GemPixUtil.cpp, but is also a member variable of GemPixObj(), or is it set up in GemMan? Should there be two checks like this, or has cvs gotten screwed up (really a whole topic)?
...in any event, I'll look into id'ing g3/g4/g5...
jamie
On Mar 24, 2006, at 1:42 PM, james tittle wrote:
...this seems like a good thing (I'd like to also add a runtime check for g4 and g5 seperation...), but it's not working on this end atm...
...I'm a bit confused as to how it's supposed to work: "m_simd" is a static variable in GemPixUtil.cpp, but is also a member variable of GemPixObj(), or is it set up in GemMan? Should there be two checks like this, or has cvs gotten screwed up (really a whole topic)?
...this sux, I can't get it to work: I can't understand why we'd want more than one check for cpu type? Is it likely that a process will init and start running on one cpu, then switch to a different type (not talking about core-duo's here)? I don't think so...
...also, are you expecting the static declaration of m_simd in GemPixUtil.cpp to actually work, because it doesn't on OSX: why not have a GemMan global variable, then refer to it via GemMan::m_simd?
...without hearing your thoughts behind it, I have to abandon my work on the color conversion routines...come to think of it, nothing has been quite right this whole day...
james
james tittle wrote:
On Mar 24, 2006, at 1:42 PM, james tittle wrote:
...this seems like a good thing (I'd like to also add a runtime check for g4 and g5 seperation...),
yes this would be good to have.
...I'm a bit confused as to how it's supposed to work: "m_simd" is a static variable in GemPixUtil.cpp, but is also a member variable of GemPixObj(), or is it set up in GemMan? Should there be two checks like this, or has cvs gotten screwed up (really a whole topic)?
no, the cvs has not screwed up. what IS screwed up, is that i called it "m_simd" everywhere.
...this sux, I can't get it to work: I can't understand why we'd want more than one check for cpu type? Is it likely that a process will init and start running on one cpu, then switch to a different type (not talking about core-duo's here)? I don't think so...
no of course not. the idea of GemSIMD is to only have 1 check.
...also, are you expecting the static declaration of m_simd in GemPixUtil.cpp to actually work, because it doesn't on OSX: why not have a GemMan global variable, then refer to it via GemMan::m_simd?
that is basically how it is, thought the variable is not in GemMan but rather in GemSIMD. i don't know whether it was a good idea to not put it into GemMan, but i liked it, because currently everything is in GemMan and that is quite a lot...
...without hearing your thoughts behind it, I have to abandon my work
my reasoning is such: only check for the CPU-type once (at run-time). depending on the type of CPU perform optimized routines. (ok that was the easy part).
this is how it works: all handling of SIMD-code is within GemSIMD. there is a GemSIMD-class, which does the actual querying of the cpu. this class is basically all static (very much like GemMan). however, the runtime-check has to be performed once, which is (for implementation reasons) done, when an instance of the GemSIMD class is created. usually only one single instance of GemSIMD will be created during the life-cycle of Gem, serving as an initialization of the cpu-check. this instantiation is done in GemMan (right after the splash-screen).
now GemSIMD provides a static variable "cpuid" which shows the capability of the used cpu. this variable could be accessed like the static variables in GemMan (e.g. GemMan::simd). however, i have done it via a (static) function call to GemSIMD::getCPU(), because this ensures that the variable cannot be modified from outside. instead there is a another (static function GemSIMD::requestCPU() where you could set the cpuid (as returned by getCPU()) to something else that is supported by your cpu. e.g. a G5 could be either altivec OR generic. an amd64 could be either sse2 OR mmx OR generic. usually getCPU() will return the best instruction set that is supported.
why would somebody want this? i am not sure. it is just possible. of course it is great if you want to do speed comparisions - but that is normally not important outside of the development. another aspect is, that sometimes SIMD and non-SIMD implementations do not behave exactly the same (though they should); by being able to chose non-SIMD operation, people have some control on what is going on.
how do the actual processing routines get called? currently only GemPixObj and the imageStruct-class (GemPixUtil) make use of this SIMD-system. there behaviour is independent (though similar). ..in GemPixObj there is (historically) a m_simd flag which is used to select the processing-implementation. this can be set via a "simd $1" message to the pix-object. this way you can turn on/off the level of optimization individually for each object. the m_simd flag is modified via the GemSIMD::requestCPU(), in order to assure that it is always supported by the used cpu. ..in imageStruct there is a global variable, which also is called m_simd (but does not influence the one in GemPixObj); this variable is global (to the file)/static because i didn't want to have an extra variable for each image denoting, whether this image should be processed with/out SIMD. A better solution would have been, to use GemSIMD::getCPU() instead of m_simd. it was just a vague idea of performance loss that led to the current solution. (i am also not sure, whether it is significantly slower to use a function-call to getCPU() instead of directly accessing cpuid: chances are high it is!)
i hope this sheds some light on what i thought and i hope it is not completely non-sense.
basically i think we think alike. it is just implementation details (like wanting to protect a variable from other classes)
on the color conversion routines...come to think of it, nothing has been quite right this whole day...
be assured, you are not the only one who feels like this (esp. today!)
mfg.adsr. IOhannes
On Mar 24, 2006, at 4:32 PM, IOhannes m zmoelnig wrote:
usually only one single instance of GemSIMD will be created during the life-cycle of Gem, serving as an initialization of the cpu-check. this instantiation is done in GemMan (right after the splash-screen).
...splash screen? I saw this committed, but what's the idea of it? Is this something to come up when Gem is loaded? Or when a gemwin is opened?
now GemSIMD provides a static variable "cpuid" which shows the capability of the used cpu. this variable could be accessed like the static variables in GemMan (e.g. GemMan::simd). however, i have done it via a (static) function call to GemSIMD::getCPU(), because this ensures that the variable cannot be modified from outside. instead there is a another (static function GemSIMD::requestCPU() where you could set the cpuid (as returned by getCPU()) to something else that is supported by your cpu. e.g. a G5 could be either altivec OR generic. an amd64 could be either sse2 OR mmx OR generic. usually getCPU() will return the best instruction set that is supported.
...this sounds fine, but the GemSIMD::getCPU() static variable in GemPixUtil.cpp isn't working for me: it always remains 0, whereas GemSIMD::cpuid does show "3"...perhaps we should just make it defined in GemMan like most things, then "extern static int m_simd;" in source files when needed?
why would somebody want this? i am not sure. it is just possible. of course it is great if you want to do speed comparisions - but that is normally not important outside of the development. another aspect is, that sometimes SIMD and non-SIMD implementations do not behave exactly the same (though they should); by being able to chose non-SIMD operation, people have some control on what is going on.
...ok, I'm all for doing it if it buys us more flexibility at no cost, even if we rarely use it...
how do the actual processing routines get called? currently only GemPixObj and the imageStruct-class (GemPixUtil) make use of this SIMD-system. there behaviour is independent (though similar). ..in GemPixObj there is (historically) a m_simd flag which is used to select the processing-implementation. this can be set via a "simd $1" message to the pix-object. this way you can turn on/off the level of optimization individually for each object. the m_simd flag is modified via the GemSIMD::requestCPU(), in order to assure that it is always supported by the used cpu. ..in imageStruct there is a global variable, which also is called m_simd (but does not influence the one in GemPixObj); this variable is global (to the file)/static because i didn't want to have an extra variable for each image denoting, whether this image should be processed with/ out SIMD. A better solution would have been, to use GemSIMD::getCPU() instead of m_simd. it was just a vague idea of performance loss that led to the current solution. (i am also not sure, whether it is significantly slower to use a function-call to getCPU() instead of directly accessing cpuid: chances are high it is!)
...I don't know what the function overhead would be, but isn't it minimal when dealing with a basic accessor function to a c++ class member variable? Would this be a candidate for inline-ing?
jamie