I have written some AVX2 code to run on a Haswell i7 processor. The same codebase is also used on non-Haswell processors, where the same code should be replaced with their SSE equivalents. I was wondering is there a way for the compiler to ignore AVX2 instructions on non-Haswell processors. I need something like:
public void useSSEorAVX(...){
IF (compiler directive detected AVX2)
AVX2 code (this part is ready)
ELSE
SSE code (this part is also ready)
}
}
Right now I am commenting out related code before compiling but there must be some more efficient way to do this. I am using Ubuntu and gcc. Thanks for your help.
I don't think it's a good idea to make separate executable unless you have to. In your case you can make a CPU dispatcher. I did this recently for GCC and Visual studio.
Let's assume you have a function called
product
for SSE and AVX. You put the SSE version in a file product_SSE.cpp and the AVX2 version in a file product_AVX2.cpp. You compile each one separately (e.g. with-msse2
and-mavx2
). Then make a module like this:You compile that module with the lower common instruction set (e.g. with SSE2). Now when you call product it first calls
product_dispatch
sets the function pointerfp
to eitherproduct_AVX2
orproduct_SSE
and then calls the function from the function pointer. The second time you callproduct
it jumps right toproduct_AVX2
orproduct_SSE
. This way you don't have to have separate executable.If you just want to do this at compile-time then you can do this:
Note that when you compile with
gcc -mavx2 ...
then__AVX2__
gets defined automatically. Similarly for__SSE__
. (Note also that you can check what's pre-defined by your compiler for any given command line switching using the incantationgcc -dM -E -mavx2 - < /dev/null
.)If you want to do run-time dispatching though then that's a little more complicated.