Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way in C to check at compile time if you are on an architecture where multiplication is fast?

Is there any way for C code to tell whether it is being compiled on an architecture where multiplication is fast? Is there some macro __FAST_MULT__ or something which is defined on those architectures?

For example, assume you are implementing a function to determine the Hamming weight of a 64-bit integer via the shift-and-add method*. There are two optimal algorithms for that: one requires 17 arithmetic operations, while the other requires only 12, but one of those is a multiplication operation. The second algorithm is thus 30% faster, if you are running on hardware where multiplication takes the same amount of time as addition - but much, much slower on a system where multiplication is implemented as repeated addition.
Thus, when writing such a function, it would be useful to be able to check at compile time whether this is the case, and switch between the two algorithms as appropriate:

unsigned int popcount_64(uint64_t x) {
    x -= (x >> 1) & 0x5555555555555555;                             // put count of each 2 bits into those 2 bits
    x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333); // put count of each 4 bits into those 4 bits
    x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f;                        // put count of each 8 bits into those 8 bits
#ifdef __FAST_MULT__
    return (x * 0x0101010101010101)>>56;                            // returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ...
#else // __FAST_MULT__
    x += x >>  8;                                                   // put count of each 16 bits into their lowest 8 bits
    x += x >> 16;                                                   // put count of each 32 bits into their lowest 8 bits
    x += x >> 32;                                                   // put count of each 64 bits into their lowest 8 bits
    return x & 0x7f;
#endif // __FAST_MULT__
}

Is there any way to do this?

* Yes, I am aware of the __builtin_popcount() functions; this is just an example.

like image 773
macdjord Avatar asked Jun 09 '16 14:06

macdjord


2 Answers

Is there any way for C code to tell whether it is being compiled on an architecture where multiplication is fast? Is there some macro __FAST_MULT__ or something which is defined on those architectures?

No, standard C does not provide any such facility. It is possible that particular compilers provide such a thing as an extension, but I am not specifically aware of any that actually do.

This sort of thing can be tested during build configuration, for example via Autoconf or CMake, in which case you can provide the symbol yourself where appropriate.

Alternatively, some C compilers definitely do provide macros that indicate the architecture for which the code is being compiled. You can use that in conjunction with knowledge of the details of various machine architectures to choose between the two algorithms -- that's what such macros are intended for, after all.

Or you can rely on the person building the program to choose, by configuration option, by defining a macro, or whatever.

like image 73
John Bollinger Avatar answered Oct 21 '22 00:10

John Bollinger


I don't believe there is a predefined macro that specifically addresses the fast multiplication feature.

There are, however, a lot of predefined compiler macros for different architectures so if you already know in advance what architectures or CPUs support the fast multiplication instruction, you can use those macros do define your own application-specific one that signifies the fast multiplication.

E.g.:

#if (defined __GNUC__ && defined __arm__ && defined __ARM_ARCH_'7'__) ||
    (defined __CC_ARM && (__TARGET_ARCH_ARM == 7))
#define FAST_MULT
#endif
like image 22
s7amuser Avatar answered Oct 21 '22 00:10

s7amuser