我在std::vector上重载了算术/赋值运算符,以便能够执行一些基本的线性代数运算。但是,在链接这些操作时遇到一些性能问题。

这是我的main.h的内容:

#include <vector>
#include <stdlib.h>

using namespace std;

typedef vector<float> vec;

inline vec& operator+=(vec& lhs, const vec& rhs) {
    for (size_t i = 0; i < lhs.size(); ++i) {
        lhs[i] += rhs[i];
    }
    return lhs;
}

inline vec operator*(float lhs, vec rhs) {
    for (size_t i = 0; i < rhs.size(); ++i) {
        rhs[i] *= lhs;
    }
    return rhs;
}


main1.cpp的内容:

#include "main.h"

// gcc 4.9.2 (-O3): 0m5.965s
int main(int, char**) {
    float x = rand();
    vec v1(1000);
    vec v2(1000);

    for (size_t i = 0; i < v1.size(); ++i) {
        v1[i] = rand();
        v2[i] = rand();
    }

    for (int i = 0; i < 10000000; ++i) {
        v1 += x * v2;

        // same as:
        //vec y = x * v2;
        //v1 += y;
    }
    return 0;
}


main2.cpp的内容:

#include "main.h"

// gcc 4.9.2 (-O3): 0m2.400s
int main(int, char**) {
    // same stuff

    for (int i = 0; i < 10000000; ++i) {
        for (size_t j = 0; j < v1.size(); ++j) {
            v1[j] += x * v2[j];
        }
    }
    return 0;
}


第二个程序的运行速度比第一个程序快得多。我确实理解为什么会这样:第一个程序执行两个循环,而不仅仅是一个循环,它分配了一个临时向量。

但是,我希望编译器能够看到并优化这种东西。还是我做错了什么?

我不记得线性代数库(例如Armadillo)遇到这个问题。他们如何解决这个问题?这是否涉及一些复杂的模板编程,还是有一些简单的方法来帮助编译器对此进行优化?

最佳答案

对于这个问题,有一些超级丑陋的模板元编程解决方案。但是随后,标准委员会发明了右值引用和移动语义的结合。查找这些内容,找到许多解决方案的示例,而没有元编程的荒谬水平。

关于c++ - 链接运算符时的编译器优化,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33154161/

10-11 22:46
查看更多