0

I have some C function which, among other things, does a modulo operation. So it looks something like

const int M = 641;

void func( ...parameters..) {
   int x;

   ... some operations ...

   x %= M;

   ... some more operations ...
}

Now, what is crucial for me is that the number M here is a constant. If I would not tell the compiler that M is a constant, then I would get much slower performance.

Currently, I am very happy with my function func( .. ) , and I want would like to extend it, so it can work on different moduli. But again, it is crucial here that these moduli are fixed. So I would like to be able to do something like

const int arrayM[] = {641, 31, 75, 81, 123};

and then have for each index in the array of constants array_M[i] a version of the function func, say func_i, which is a copy of the function func, but where array_M[i] replaces the role of M.

In practice, my array of constants arrayM[] will consist of around 600 explicit prime numbers, which I will choose in a particular way so that x % array_M[i] compiles to a very fast modulus function (for instance Mersenne primes).

My question is: How do I do this in C without making 600 copies of my function func, and changing the variable M in the code each time ?

Finally, I would like to ask the same question again for CUDA code. So if I would have a cuda-kernel, where at some point in the code a modulus M operation is carried out, and I want to have different copies of the same kernel (one for each index of array_M).

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
mnr
  • 604
  • 2
  • 7
  • 15
  • 2
    *If I would not tell the compiler that M is a constant, then I would get much slower performance.* - Really? Have you quantified it yet? – Eugene Sh. Jun 22 '17 at 14:49
  • 1
    What makes you think there will be any difference? – Jabberwocky Jun 22 '17 at 14:49
  • 1
    CUDA is not C ! One question&language per post! "the number M here is a constant" - That's wrong! C does not have symbolic constants of user-defined type. `const` does **not** mean "constant". If your C book states different, get a better one. – too honest for this site Jun 22 '17 at 14:50
  • 1
    "If I would not tell the compiler that M is a constant, then I would get much slower performance." - How do you know? Show how you profiled and which difference it made. – too honest for this site Jun 22 '17 at 14:54
  • 2
    CUDA is not a language and is usable with C. So the "one language" hint doesn't apply here. But as the question doesn't show any code using CUDA, it's still a pure C question. –  Jun 22 '17 at 14:57
  • 1
    Assuming that the statement "get much slower performance" is true, are you forced to stick with plain C? C++ templates would work perfectly here. In fact, you could use them in CUDA already. – Davide Spataro Jun 22 '17 at 14:57

2 Answers2

3

You may use a define like:

#define F(i,n)  void func_##i() { printf("%d\n",n); }

#include <stdio.h>

F(1,641)
F(2,31)
...

int main() {
    func_1();
    func_2();
}

It is possible to obtain the same effect from a list of constant but it is much much more tricky. See recursive macro.

Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69
1

Most compilers will do constant propagation. You need to turn up the optimisation level high. The only way to be sure however is to examine the assembly code, or to explicitly write the code out with the constants folded in, which is ugly and hard to maintain. C++ allows you to specify a scalar as a template.

Malcolm McLean
  • 6,258
  • 1
  • 17
  • 18