
ESP_LOGI 间隔 163813 微秒,平均下来一次 float 计算要 1 微秒,与芯片性能严重不符。请问是什么原因导致的呢?#include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_system.h" #include "esp_log.h" #define M2T(X) ((unsigned int)(X) / portTICK_PERIOD_MS) // ms to tick #include "esp_random.h" #include <sys/time.h> static const char *TAG = "main"; #define dataLen 14400 void makeMatrixUint8(uint8_t *buf, int len) { for (int i = 0; i < len; i++) { esp_fill_random(&buf[i], sizeof(uint8_t)); } } void makeMatrixFloat(float *buf, int len) { for (int i = 0; i < len; i++) { esp_fill_random(&buf[i], sizeof(float)); } } static void testTask() { uint8_t *testData1 = (uint8_t *)malloc(sizeof(uint8_t) * dataLen); float *testData2 = (float *)malloc(sizeof(float) * dataLen); struct timeval tv_d0; struct timeval tv_d1; while (1) { makeMatrixUint8(testData1, dataLen); makeMatrixFloat(testData2, dataLen); gettimeofday(&tv_d0, NULL); for (int t = 0; t < 10; t++) { for (int i = 0; i < dataLen; i++) { testData2[i] = testData1[i] * 0.3; } } gettimeofday(&tv_d1, NULL); ESP_LOGI(TAG, "%lu", 1000000 * (tv_d1.tv_sec - tv_d0.tv_sec) + (tv_d1.tv_usec - tv_d0.tv_usec)); vTaskDelay(1); } } void app_main() { xTaskCreate(testTask, "servoTask", 1024 * 4, NULL, tskIDLE_PRIORITY, NULL); }
1 zk8802 2023 年 4 月 12 日 看一下编译生成的二进制代码,里面的浮点运算是软件模拟的浮点指令还是硬件浮点指令? |
2 geekzjj 2023 年 4 月 12 日 via Android gettimeofday 以及 log 函数本身的性能损耗测过吗? |
3 biggates 2023 年 4 月 12 日 你用 `esp_fill_random()` 的话,是不是只要把整个 `buf` fill 一次就行了,不需要循环去 fill 每个元素? |
4 biggates 2023 年 4 月 12 日 原文: This function automatically busy-waits to ensure enough external entropy has been introduced into the hardware RNG state, before returning a new random number. This delay is very short (always less than 100 CPU cycles). 所以你 dataLen 14400 的时候,每次 delay 加起来就很大了。src: https://docs.espressif.com/projects/esp-idf/zh_CN/v4.4.4/esp32/api-reference/system/random.html#_CPPv410esp_randomv |
5 Leon6868 OP |
6 misdake 2023 年 4 月 13 日 via Android 0.3 改成 0.3f |
7 misdake 2023 年 4 月 13 日 via Android godbolt 反汇编: https://godbolt.org/z/or71efds8 double 乘法还是走的软件模拟,类型转换也是。会先后调用 floatsidf muldf3 truncdfsf2 这三个函数,所以很慢吧。 改成 0.3f 之后,就全是正常指令了,float.s mul.s 这类,不需要调用其他方法。 |
8 misdake 2023 年 4 月 13 日 via Android esp32-s3 模拟: https://wokwi.com/projects/361855375362930689 0.3 打印的时间是 1891678 0.3f 打印的时间是 166518 性能提高 10 倍 |
9 misdake 2023 年 4 月 13 日 via Android 作为对比,去掉* 0.3 的代码,只做类型转换 testData2[i] = testData1[i],模拟器打印时间是 116627 ,和 0.3f 的版本相比性能提升幅度很合理 |