Author Topic: Nuclear Option  (Read 1413 times)

Robert

  • Hero Member
  • *****
  • Posts: 1190
    • View Profile
Nuclear Option
« on: March 21, 2024, 05:38:31 PM »
Add ATOMIC case insensitive data type qualifier.

Useful for preemptively stopping compilers from optimizing out loops as well as preventing trouble with multi-threaded apps.

Compile attached code with LLVM or LLVM-MinGW with -O2 optimizing and all the loops are optimized out resulting in

Code: [Select]
Time for             recursive:          0
Time for      divide-iterative:          0
Time for    multiply-iterative:          0
Time for         if-statements:          0
Time for reverse-if-statements:          0
Time for                log-10:         61
Time for           binary chop:          0

Go  ATOMIC by

Code: [Select]
... clearing the comment  operator "//" from line 6
... clearing the comment  operator "//" from line 121
... adding a comment operator "//" to line 122

compile and the compiler avoids optimizing out the ATOMIC protected loop resulting in

Code: [Select]

Time for             recursive:        571
Time for      divide-iterative:        478
Time for    multiply-iterative:        364
Time for         if-statements:        392
Time for reverse-if-statements:        274
Time for                log-10:       1255
Time for           binary chop:        314

Atomic types documented here

https://en.cppreference.com/w/c/language/atomic

MrBcx

  • Administrator
  • Hero Member
  • *****
  • Posts: 2039
    • View Profile
Re: Nuclear Option
« Reply #1 on: March 21, 2024, 06:41:50 PM »
That's an interesting language feature request Robert.

It seems like an easy request but the devil is always in the details.

If I can't knock it out quickly, it may have to go on my summer to-do list.

I've attached my results using Pelles C v12

jbk

  • Full Member
  • ***
  • Posts: 211
    • View Profile
Re: Nuclear Option
« Reply #2 on: March 21, 2024, 07:43:34 PM »
here are my times
clang non-atomic, clang from https://github.com/mstorsjo/llvm-mingw/releases
Code: [Select]
Time for             recursive:          0
Time for      divide-iterative:          0
Time for    multiply-iterative:          0
Time for         if-statements:          0
Time for reverse-if-statements:          0
Time for                log-10:         78
Time for           binary chop:          0
atimic
Code: [Select]
Time for             recursive:       1349
Time for      divide-iterative:       1350
Time for    multiply-iterative:       1114
Time for         if-statements:       1130
Time for reverse-if-statements:       1177
Time for                log-10:       3860
Time for           binary chop:       1256
g++ 13.2 non-atomic -O2 , g++ from https://winlibs.com/
Code: [Select]
Time for             recursive:        548
Time for      divide-iterative:        487
Time for    multiply-iterative:        471
Time for         if-statements:        377
Time for reverse-if-statements:        423
Time for                log-10:       1287
Time for           binary chop:        393
I don't like the atomic times, they are about 2 times slower than g++
am also surprised that g++ didn't eliminate the loops
« Last Edit: March 21, 2024, 07:58:49 PM by jbk »

MrBcx

  • Administrator
  • Hero Member
  • *****
  • Posts: 2039
    • View Profile
Re: Nuclear Option
« Reply #3 on: March 22, 2024, 10:13:07 AM »
I don't like the atomic times, they are about 2 times slower than g++

My understanding is that the use of atomic's are mainly for interrupt and threaded
operations, not for speeding up one's app.  The example that Robert posted appears
to show the effects of bad optimizing ( zero timing results ) when atomic's are not used
and the compiler was overly aggressive with its optimizing (not a new phenomenon.)  The
example is meant to force compilers to not optimize code containing atomic variables.
In other words, slow working code is better than fast broken code.

I reserve my right to be wrong.

jbk

  • Full Member
  • ***
  • Posts: 211
    • View Profile
Re: Nuclear Option
« Reply #4 on: March 22, 2024, 10:19:49 AM »
I prefer
Code: [Select]
#pragma GCC push_options
#pragma GCC optimize("O0")
// your code here
#pragma GCC pop_options

jbk

  • Full Member
  • ***
  • Posts: 211
    • View Profile
Re: Nuclear Option
« Reply #5 on: March 22, 2024, 06:27:07 PM »
using clang with atomic I get
Code: [Select]
Time for             recursive:       1349
Time for      divide-iterative:       1350
Time for    multiply-iterative:       1114
Time for         if-statements:       1130
Time for reverse-if-statements:       1177
Time for                log-10:       3860
Time for           binary chop:       1256
if instead of atomic I do
only the main function from Robert's code posted below with the addition of a pragma
Code: [Select]
#pragma clang optimize off
int main (int c, char *v[]) {
//  _Atomic int i, j, k, r;
    int i, j, k, r;
    int s = 1;

    /* Test code:
        printf ("%11d %d\n", INT_MIN, count_recur(INT_MIN));
        for (i = -1000000000; i != 0; i /= 10)
            printf ("%11d %d\n", i, count_recur(i));
        printf ("%11d %d\n", 0, count_recur(0));
        for (i = 1; i != 1000000000; i *= 10)
            printf ("%11d %d\n", i, count_recur(i));
        printf ("%11d %d\n", 1000000000, count_recur(1000000000));
        printf ("%11d %d\n", INT_MAX, count_recur(INT_MAX));
    */

    /* Randomize and create random pool of numbers. */

    srand (time (NULL));
    for (j = 0; j < numof (rndnum); j++) {
        rndnum[j] = s * rand();
        s = -s;
    }
    rndnum[0] = INT_MAX;
    rndnum[1] = INT_MIN;

    /* For testing. */
    for (k = 0; k < numof (rndnum); k++) {
        rt[k] = (fn[1].fnptr)(rndnum[k]);
    }

    /* Test each of the functions in turn. */

    clk[0] = clock();
    for (i = 1; i < numof (fn); i++) {
        for (j = 0; j < 10000; j++) {
            for (k = 0; k < numof (rndnum); k++) {
                r = (fn[i].fnptr)(rndnum[k]);
                /* Test code:
                    if (r != rt[k]) {
                        printf ("Mismatch error [%s] %d %d %d %d\n",
                            fn[i].desc, k, rndnum[k], rt[k], r);
                        return 1;
                    }
                */
            }
        }
        clk[i] = clock();
    }

    /* Print out results. */

    for (i = 1; i < numof (fn); i++) {
        printf ("Time for %s: %10d\n", fn[i].desc, (int)(clk[i] - clk[i-1]));
    }

    return 0;
}
my time is
Code: [Select]
Time for             recursive:        658
Time for      divide-iterative:        566
Time for    multiply-iterative:        438
Time for         if-statements:        519
Time for reverse-if-statements:        502
Time for                log-10:       2730
Time for           binary chop:        487
unfortunately pragmas can not be used inside a function

you cal also use __attribute__ ((optnone)) but I prefer the pragma, it's cleaner syntax and you can also turn optimize back on with #pragma clang optimize on
« Last Edit: March 22, 2024, 06:43:04 PM by jbk »

Robert

  • Hero Member
  • *****
  • Posts: 1190
    • View Profile
Re: Nuclear Option
« Reply #6 on: March 22, 2024, 07:39:31 PM »
I prefer
Code: [Select]
#pragma GCC push_options
#pragma GCC optimize("O0")
// your code here
#pragma GCC pop_options

Thanks for your posts jbk.

BCX
$OPTIMIZE OFF/ON
currently supports only LCC and Pelles C

Maybe MrBcx can add, to his to do list, an update for other compilers.

Microsoft
https://learn.microsoft.com/en-us/cpp/preprocessor/optimize?view=msvc-170

Using the optimize pragma with the empty string ("") is a special form of the directive:

When you use the off parameter, it turns all the optimizations, g, s, t, and y, off.

When you use the on parameter, it resets the optimizations to the ones that you specified using the /O compiler option.

Code: [Select]
#pragma optimize( "", off )
/* unoptimized code section */
#pragma optimize( "", on )

gcc
https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Function-Specific-Option-Pragmas.html#Function-Specific-Option-Pragmas

Code: [Select]
#pragma GCC push_options
#pragma GCC optimize("O0")
// your code here
#pragma GCC pop_options

clang
https://clang.llvm.org/docs/LanguageExtensions.html#extensions-for-selectively-disabling-optimization

Code: [Select]
#pragma clang optimize off

#pragma clang optimize on

References
https://stackoverflow.com/questions/31373885/how-to-change-optimization-level-of-one-function
 

MrBcx

  • Administrator
  • Hero Member
  • *****
  • Posts: 2039
    • View Profile
Re: Nuclear Option
« Reply #7 on: March 23, 2024, 09:23:35 AM »
unfortunately pragmas can not be used inside a function

JB,

ChatGpt and Google Gemini both dispute your statement.

Can you post your reference?

I will extend BCX's Optimize Directives for Gcc, Clang, and MSVC but I want to do it correctly.

Thanks


jbk

  • Full Member
  • ***
  • Posts: 211
    • View Profile
Re: Nuclear Option
« Reply #8 on: March 23, 2024, 10:11:15 AM »
MrBcx, in my web search I don't know for certain if I came across documentation that states that the optimize pragma can't be used inside a function, but gcc-13.2 gives this error if the pragma is inside the function main of the example that we have been testing LengthOfInteger.cpp:142:9: error: '#pragma GCC optimize' is not allowed inside functions
clang is happy to compile the program if the clang pragma is inside main but it's completely ignored, perhaps other pragmas are allowed inside functions but not optimize
I will search the web for documentation
« Last Edit: March 23, 2024, 10:44:38 AM by jbk »

MrBcx

  • Administrator
  • Hero Member
  • *****
  • Posts: 2039
    • View Profile
Re: Nuclear Option
« Reply #9 on: March 23, 2024, 12:19:24 PM »
MrBcx, in my web search I don't know for certain if I came across documentation that states that the optimize pragma can't be used inside a function, but gcc-13.2 gives this error if the pragma is inside the function main of the example that we have been testing LengthOfInteger.cpp:142:9: error: '#pragma GCC optimize' is not allowed inside functions
clang is happy to compile the program if the clang pragma is inside main but it's completely ignored, perhaps other pragmas are allowed inside functions but not optimize
I will search the web for documentation

JB -- I get a different experience than you. 

When I apply the appropriate #pragma statements cited above to clang and clang++ and gcc and g++ command lines, things work as expected.
Not only do I not get the error message that you reported, I also get correct executables using the #pragmas, albeit the timings are slightly
different (not unexpected) when using clang/clang++  and gcc/g++.

I've been using CLANG from the official LLVM-17.0.2 released in October 2023

and using gcc / g++ from Martin Storsjo's

llvm-mingw-20240308-ucrt-x86_64 from March 2024, which might explain some differences.

For now, I'm simply going to follow my nose and see where it takes me.


jbk

  • Full Member
  • ***
  • Posts: 211
    • View Profile
Re: Nuclear Option
« Reply #10 on: March 23, 2024, 12:32:29 PM »
MrBcx
the more recent gcc toolchainns have much better warning and error reporting, if you try the example with gcc-13.2 or above you will see the error message
<edit>
are you using llvm-g++?
llvm g++ simply calls clang and clang does not report the pragma inside a function as an error but simply ignores it
you need to use an non-llvm g++ 13.2 or better, but I won't bother you anymore
« Last Edit: March 23, 2024, 01:04:31 PM by jbk »

MrBcx

  • Administrator
  • Hero Member
  • *****
  • Posts: 2039
    • View Profile
Re: Nuclear Option
« Reply #11 on: March 23, 2024, 01:16:55 PM »
llvm g++ simply calls clang and clang does not report the pragma inside a function as an error but simply ignores it
you need to use an non-llvm g++ 13.2 or better, but I won't bother you anymore

Bingo!  That was news to me.  The whole point to my choosing Martin Storsjo's package was
to get away from the issues with the Winlib and Equation Solutions packages. 
That said, I have no desire to play musical chairs with various Mingw installations anymore.


Robert

  • Hero Member
  • *****
  • Posts: 1190
    • View Profile
Re: Nuclear Option
« Reply #12 on: March 23, 2024, 01:33:26 PM »
llvm g++ simply calls clang and clang does not report the pragma inside a function as an error but simply ignores it
you need to use an non-llvm g++ 13.2 or better, but I won't bother you anymore

Bingo!  That was news to me.  The whole point to my choosing Martin Storsjo's package was
to get away from the issues with the Winlib and Equation Solutions packages. 
That said, I have no desire to play musical chairs with various Mingw installations anymore.

Nuwen 19.0 (64 bit only) from
https://nuwen.net/mingw.html

GCC 13.2.0

Code: [Select]
! #pragma GCC push_options
! #pragma GCC optimize("O0")
FOR INTEGER i = 1 TO 10
 ? LPAD$(STR$(i, 1), 3, ASC("0"))
NEXT
! #pragma GCC pop_options

PAUSE
Code: [Select]
Compiling "E:\t\Temp.cpp" with Nuwen g++.exe
E:\t\Temp.cpp: In function 'int main(int, char**)':
E:\t\Temp.cpp:232:12: error: '#pragma GCC optimize' is not allowed inside functions
  232 |    #pragma GCC optimize("O0")
      |            ^~~

Possible partial solution at

https://stackoverflow.com/questions/62529457/pragma-gcc-optimize-in-function