www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Preventing the Compiler from Optimizing Away Benchmarks

reply jmh530 <john.michael.hall gmail.com> writes:
I was looking at [1] for ways to prevent the compiler from 
optimizing away code when trying to benchmark.

It has the following C++ code as a simpler version:
```
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
     asm volatile("" : "+r,m"(value) : : "memory");
}
```

I made an attempt to make a D version of it, but failed. 
Apparently DMD doesn't like the `""` in the first part of the asm 
instruction. I'm also not sure the `volatileLoad` command is 
right, but I didn't know of any other way to have volatile work 
in D (and I couldn't figure out how it actually worked from 
looking at the code).

```
void DoNotOptimize(T)(T* ptr)
{
     import core.volatile: volatileLoad;
     T value = volatileLoad(ptr);
     asm {"" : "+r,m"(value) : : "memory";}
}
```

[1] 
https://theunixzoo.co.uk/blog/2021-10-14-preventing-optimisations.html
Mar 13 2023
parent reply user1234 <user1234 12.de> writes:
On Monday, 13 March 2023 at 14:17:57 UTC, jmh530 wrote:
 I was looking at [1] for ways to prevent the compiler from 
 optimizing away code when trying to benchmark.

 It has the following C++ code as a simpler version:
 ```
 inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
     asm volatile("" : "+r,m"(value) : : "memory");
 }
 ```

 I made an attempt to make a D version of it, but failed. 
 Apparently DMD doesn't like the `""` in the first part of the 
 asm instruction. I'm also not sure the `volatileLoad` command 
 is right, but I didn't know of any other way to have volatile 
 work in D (and I couldn't figure out how it actually worked 
 from looking at the code).

 ```
 void DoNotOptimize(T)(T* ptr)
 {
     import core.volatile: volatileLoad;
     T value = volatileLoad(ptr);
     asm {"" : "+r,m"(value) : : "memory";}
 }
 ```

 [1] 
 https://theunixzoo.co.uk/blog/2021-10-14-preventing-optimisations.html
that's illegal code. You mix GCC/LLVM syntax with D asm block and the front-end wont recognize that. LDC recognizes a syntax similar to what is described in your link, see https://wiki.dlang.org/LDC_inline_assembly_expressions. GDC has it too (since that the syntax invented by GCC in first place) but I cant find the documentation ATM.
Mar 13 2023
parent jmh530 <john.michael.hall gmail.com> writes:
On Monday, 13 March 2023 at 15:23:25 UTC, user1234 wrote:
 [snip]
 [1] 
 https://theunixzoo.co.uk/blog/2021-10-14-preventing-optimisations.html
that's illegal code. You mix GCC/LLVM syntax with D asm block and the front-end wont recognize that. LDC recognizes a syntax similar to what is described in your link, see https://wiki.dlang.org/LDC_inline_assembly_expressions. GDC has it too (since that the syntax invented by GCC in first place) but I cant find the documentation ATM.
Thanks, that helps. Below seems to be working...(with LDC and -O) when I include the DoNotOptimize, it takes around 300-500us, but when I comment it out, then it takes about 5us. It would still take some work to figure out how to get it to work with DMD. ```d void DoNotOptimize(T)(T* ptr) { import ldc.llvmasm; import core.volatile: volatileLoad; T value = volatileLoad(ptr); __asm("", "*mr,~{memory}", &value, ); } void main() { import std.algorithm.iteration: sum; import std.array: uninitializedArray; import std.datetime.stopwatch; import std.random: uniform; import std.stdio: writeln; auto testData = uninitializedArray!(long[])(600_000); foreach(ref el; testData) el = uniform(0, 10); ulong seed = 0; ulong output = 0; StopWatch sw; sw.start(); DoNotOptimize(&seed); output = testData.sum(seed); DoNotOptimize(&output); sw.stop(); writeln("time: ", sw.peek); } ```
Mar 13 2023