Should I store C array values ​​in local variables if I am going to reference them repeatedly?

I am writing optimized C code that basically goes through an array and does something for each element. What this does is dependent on the current value of the element, something like:

for (i=0; i < a_len; i++) {
    if (a[i] == 0) {
        a[i] = f1(a[i]);
    } else if (a[i] % 2 == 0) {
        a[i] = f2(a[i]);
    } else {
        a[i] = 0;
}

I am returning to C after many years of working in dynamic languages, where my practice was to try to write simple code and not create a lot of local variables for things that I can just refer directly to, for example [i] above. I know very well that the best practices are to write readable code and trust that the compiler is smarter than you and will do good optimizations.

If I wrote the code above in assembler, I would once load [i] into the register, and then just use this value every time, because I know that [] is private memory and will not change between links. However, even an intelligent compiler can do a load every time because it cannot be sure that the memory has not changed. (Or do I need to explicitly declare "a" volatile for the compiler so as not to do this optimization?).

So my question is: should I expect performance improvements by overwriting with a local variable as follows:

for (i=0; i < a_len; i++) {
    val = a[i];
    if (val == 0) {
        a[i] = f1(val);
    } else if (val % 2 == 0) {
        a[i] = f2(val);
    } else {
        a[i] = 0;
}

Or would something like -O3 take care of this automatically for me? The code I optimize takes several days, so even minor improvements will make a difference.

+3
9

f1 f2, , . ? ? ?

if-else , . a[ i ] .

-. . , , , , ..

: , , , , a[ i ] volatile.

+3

, , // , , , .

, . , , . , , , .:)

+14

. , , , , :

for (i=0; i < a_len; i++) {

    int val = a[i];  /* or whatever type */
    int result = 0;  /* default result */

    if (val == 0) {
        result = f1(val);
    } else if (val % 2 == 0) {
        result = f2(val);
    } 

    a[i] = result;
}

, . , ( ) . , - , , .

, , , . , .

for (p=&a[0]; p < &a[a_len]; ++p) {

    int val = *p;    /* or whatever type */
    int result = 0;  /* default result */

    if (val == 0) {
        result = f1(val);
    } else if (val % 2 == 0) {
        result = f2(val);
    } 

    *p = result;
}

, , - (, ). , - ( ).

, - [i] , , .

, , , , . , . , , , . , (, MSVC ).

, , , a , , ( ).


, , ?

+7

GCC, -O . - , ( ).

+4

dirkGentley:

, , , , [ i]

, , " ". Nick, "a" , function (int * a), , "a" , , .

"int * ", , "a" .

, 100% - !

+1

C .

.

, im , "val". "val" "a" , , .

0

: " ...", , .

: , , .

0
  • , ,
  • , , .
  • ,
  • ()
-1

, var vaiable, .

int* var;//Int or whatever type a[] is
for (i=0; i < a_len; i++) {
    val = &a[i];
    if (*val == 0) {
        f1(val);//// Set the valur inside f1
    } else if (*val % 2 == 0) {
        f2(val);// Set the valur inside f2
    } else {
        *val = 0;
}

, "%", . , ( ):

#define is_divisible(dividend, divisor) ((((dividend)/(divisor)) * (divisor))==(dividend))

:

else if (is_divisible(val,2)) {

, , , .

Edit: true that the profit is not so great when using module calculations, using only "% 2". But if you ever go to a higher level than 2 to perform a modular operation, and they are just interested in the module, returns zero, then my macro is faster in all the compilers I used

-1
source

Source: https://habr.com/ru/post/1705036/


All Articles