math speed on ESP32

31 views
Skip to first unread message

Moshe Braner

unread,
Feb 26, 2025, 2:55:56 PM2/26/25
to SoftRF_community
Does anybody know of measurements of the time it takes the ESP32, using the standard libraries, to compute functions such as sin(), cos(), atan2() and hypot() at float (not double) precision?  I tried to measure it myself and the result do not make sense.  Trying to prevent compiler optimizations from short-cutting the loop is tricky.


R. van Twisk

unread,
Feb 26, 2025, 3:08:17 PM2/26/25
to Moshe Braner, SoftRF_community

On 26 Feb 2025, at 20:55, Moshe Braner <moshe....@gmail.com> wrote:

Does anybody know of measurements of the time it takes the ESP32, using the standard libraries, to compute functions such as sin(), cos(), atan2() and hypot() at float (not double) precision?  I tried to measure it myself and the result do not make sense.  Trying to prevent compiler optimizations from short-cutting the loop is tricky.

You cannot pass -O0 ? But in anycase, don't you want to measure it with -O2 at least? I thionk you need to find a way to 'trick' teh compiler to store the final result somewhere so it won't optmise results away. Any code you can share?

  



--
You received this message because you are subscribed to the Google Groups "SoftRF_community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to softrf_communi...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/softrf_community/7daf975c-6842-4faa-83bb-097c5e9b0b8dn%40googlegroups.com.

Robert J. Simpson

unread,
Feb 26, 2025, 4:34:13 PM2/26/25
to softrf_c...@googlegroups.com

I just tried on an ESP32-C3 and I measured cos at 20.3 uS.

To stop false optimization, you need to provide input values the compiler doesn't know about, or are too complex to calculate at compile time e.g.

  1. Read values from variables marked as volatile
  2. Read values from an external source e.g. analog input (but the read will likely be much longer than what you are trying to measure)
  3. Combine an external value with increments

The code I used was:

  int value = analogRead(2); 
  float val = float(value) / 4095.0;
  int64_t start_time = esp_timer_get_time();  // Get time in microseconds
  float total = 0.0;
  for (int i=0; i<1000; i++) {
    total = total + (val * float(i)/10000.0);      // A

    //total = total + cos(val * float(i)/10000.0); // B
  }
  int64_t elapsed_time = esp_timer_get_time() - start_time;
  Serial.printf("Total: %f\n", total);
  Serial.printf("Elapsed time: %lld us\n", elapsed_time);
  delay(500);

The output needs to go somewhere otherwise the compiler will treat it as unused and remove what it considers to be 'dead code'.

I ran with with A to get a baseline and then with B to measure cos.

Rob

Moshe Braner

unread,
Feb 27, 2025, 5:05:33 PM2/27/25
to SoftRF_community
There is apparently no access to the compiler options from the Arduino 1.8.19 IDE GUI.  The compiler options for ESP32 are in this file:
~/.arduino15/packages/esp32/hardware/esp32/2.0.3/platform.txt
(not this one: ~/Arduino/hardware/espressif/esp32/platform.txt)
I changed the -Os to -O0 (in 3 places, for the plain ESP32, there are separate sections for the ESP32-S3 etc).  That added about 0.5 us to each iteration, presumably by not optimizing the for() looping code.  It did not change the conclusions about the math functions: the library functions are faster than my approximate ones.  They are generally around 2-3 microseconds each (at 160 MHz CPU speed on a plain ESP32).  Amazing!

That's for the float versions.  The double versions are of course a lot slower.  I only checked sin(double), it was about 14 microseconds.  That is what happens if you use code like sin((3.1459/180)*x).  C++ treats the literal value "3.1459" as double, and since there is a sin(double), that is what it calls.  So use sin((3.1459f/180.0f)*x).  Or sin((float)(3.1459/180)*x).  That's assuming "x" is a float.
Reply all
Reply to author
Forward
0 new messages