当前位置:  开发笔记 > 编程语言 > 正文

Arduino - 通过指针传递struct似乎比按值慢

如何解决《Arduino-通过指针传递struct似乎比按值慢》经验,为你挑选了1个好方法。

我写了一些假代码,可以解释我在实际应用程序中发现的问题(Arduino 1.6 - https://github.com/maciejmiklas/LEDDisplay):

Display.h:

class Display {

public:
    void testRef();
    void testVal();

private:
    typedef struct {
            uint8_t xOnFirstKit;
            uint8_t yOnFirstKit;
            uint8_t xRelKit;
            uint8_t yRelKit;
            uint8_t xRelKitSize;
            uint8_t yRelKitSize;
            uint8_t xDataBytes;
            uint8_t xKit;
            uint8_t yKit;
            uint8_t xOnKit;
            uint8_t yOnKit;
            uint8_t xOnKitSize;
            uint8_t yOnKitSize;
            uint8_t xOnScreenIdx;
            uint8_t yOnScreenIdx;
            uint8_t yDataIdx;
        } KitData;

 inline void paintOnKitRef(KitData *kd); 
 inline void paintOnKitVal(KitData kd); 
}


Display.cpp:

#include "Display.h"

void Display::testRef(){
    KitData *kd = ....

    for(int i = 0 ; i < 5000 ; i++){
       paintOnKitRef(kd);
       ....
    }
}

void Display::testVal(){
    KitData *kd = ....

    for(int i = 0 ; i < 5000 ; i++){
       paintOnKitVal(*kd);
       ....
    }
}

inline void Display::paintOnKitRef(KitData *kd){
    for(int i = 0 ; i < 100 ; i++){
        kd->yDataIdx++;
        kd->yOnScreenIdx++;
        .....
    }
}

inline void Display::paintOnKitVal(KitData kd){
    for(int i = 0 ; i < 100 ; i++){
        kd.yDataIdx++;
        kd.yOnScreenIdx++;
        .....
    }
}

我有结构:KitData大于16个字节,所以我决定用指针而不是值传递它 - 它按预期工作.

我已经测量了执行时间,看起来像传递值(testVal())比传递引用(testRef())要快30%.

这是正常的吗?

编辑:

上面的代码只是一个伪代码 - 在我真正的测试方法中:paintOnKitVal()并且paintOnKitRef()包含执行许多操作和其他方法的实际代码.这两种方法也做同样的事情 - 唯一的区别是访问方式(通过kd指针或点表示法).

这是真正的测试类:https://github.com/maciejmiklas/LEDDisplay/blob/callByPoint/Display.cpp

    执行测试方法:paint(...)- 这将使用第211行中的call-by-pointer

    注释第211行并从第212行删除注释 - 从现在开始测试将使用按值调用,执行时间将更短.

JSF.. 5

这部分代码绝对没有任何内容,优化器会识别出:

inline void Display::paintOnKitVal(KitData kd){
    for(int i = 0 ; i < 100 ; i++){
        kd.yDataIdx++;
        kd.yOnScreenIdx++;
    }
}

你想象你测试了pass by value的性能.但是你真的测试了编译器识别代码什么都不做的事实的能力.

当您通过指针(C程序员可能通过引用调用"但C++程序员不会"通过引用)时,单独的函数不能说什么也不做.优化器需要更广泛地理解整个程序发现缺乏效果.



1> JSF..:

这部分代码绝对没有任何内容,优化器会识别出:

inline void Display::paintOnKitVal(KitData kd){
    for(int i = 0 ; i < 100 ; i++){
        kd.yDataIdx++;
        kd.yOnScreenIdx++;
    }
}

你想象你测试了pass by value的性能.但是你真的测试了编译器识别代码什么都不做的事实的能力.

当您通过指针(C程序员可能通过引用调用"但C++程序员不会"通过引用)时,单独的函数不能说什么也不做.优化器需要更广泛地理解整个程序发现缺乏效果.


如果优化器无法将您的实际代码识别为无效,则优化器仍可将其识别为**LESS**而不是指针版本的传递.编译器知道您在值传递过程中所做的任何更改都将在返回时被丢弃.
推荐阅读
地之南_816
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有