运算符重载性能

Joh*_*ohn 2 c++

我正在阅读一篇关于自动微分的论文,作者提到:“同样,使用运算符重载可能会引入伴随成本的方法调度,与原始函数的原始数值计算相比,这很容易减慢震级。”

基本上,你能解释一下关于运算符重载的引言的第一部分以及它是否适用于 C++ 吗?我真的不了解语言的内部结构。

周围的文字没有添加任何进一步的解释。

Mat*_*son 6

之间会有很大的区别:

Complex a(1.0, 2.0), b(1.1, 2.2);
Complex c;

c = a + b;
Run Code Online (Sandbox Code Playgroud)

和:

Complex a(1.0, 2.0), b(1.1, 2.2);
Complex c;

c.re = a.re + b.re;
c.im = a.im + b.im;
Run Code Online (Sandbox Code Playgroud)

如果Complex operator+(Complex lhs, Complex rhs);函数无法内联。但是,如果 compile 可以内联代码,则根本没有区别。

所以它在很大程度上取决于对运营商的调用的相对开销和实际调用的复杂性。做std::string operator+(const std::string& lhs, const std::string& rhs);一个对字符串的是几千字节将在调用的开销非常小operator+,相比的增加doublefloat在复杂的数学情况下上面的数字。对于短字符串,相对而言,开销要大得多。

下面是一个例子:

操作.cpp:

#include <iostream>
#include <cstdlib>
#include "Complex.h"
#include "Complex2.h"

const int SIZE = 80000;

template<typename CPLX> 
void Fill(CPLX* arr)
{
    for(int i = 0; i < SIZE; i++)
    {
        arr[i] = CPLX(rand(), rand());
    }
}

template<typename CPLX> 
void DummyFunc(CPLX* arr)
{
    double sum;
    for(int i = 0; i < SIZE; i++)
    {
        sum = arr[i].re + arr[i].im;
    }
    std::cout << "Sum:" << sum << std::endl;
}

static __inline__ unsigned long long rdtsc(void)
{
    unsigned hi, lo;
    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
    return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}

void RunFunc1()
{
    Complex arr1[SIZE];
    Complex arr2[SIZE];
    Complex arr3[SIZE];

    Fill(arr1);
    Fill(arr2);

    unsigned long long t = rdtsc();
    for(int i = 0; i < SIZE; i++)
    {
        arr3[i] = arr2[i] + arr1[i];
    }
    t = rdtsc() - t;
    std::cout << "Time=" << t << std::endl;
    DummyFunc(arr3);
}

void RunFunc2()
{
    Complex2 arr1[SIZE];
    Complex2 arr2[SIZE];
    Complex2 arr3[SIZE];

    Fill(arr1);
    Fill(arr2);

    unsigned long long t = rdtsc();
    for(int i = 0; i < SIZE; i++)
    {
        arr3[i] = arr2[i] + arr1[i];
    }
    t = rdtsc() - t;
    std::cout << "Time=" << t << std::endl;
    DummyFunc(arr3);
}

void RunFunc3()
{
    Complex2 arr1[SIZE];
    Complex2 arr2[SIZE];
    Complex2 arr3[SIZE];

    Fill(arr1);
    Fill(arr2);

    unsigned long long t = rdtsc();
    for(int i = 0; i < SIZE; i++)
    {
        arr3[i].im = arr2[i].im + arr1[i].im;
        arr3[i].re = arr2[i].re + arr1[i].re;
    }
    t = rdtsc() - t;
    std::cout << "Time=" << t << std::endl;
    DummyFunc(arr3);
}


int main(int argc, char **argv)
{
    RunFunc1();
    RunFunc2();
    RunFunc3();
}
Run Code Online (Sandbox Code Playgroud)

复杂.h:

class Complex
{
public:
    Complex(double r, double i) : re(r), im(i) {}
    Complex() {};
    double re;
    double im;
};

Complex operator+(Complex lhs, Complex rhs);
Run Code Online (Sandbox Code Playgroud)

复杂2.h:

class Complex2
{
public:
    Complex2(double r, double i) : re(r), im(i) {}
    Complex2() {};
    double re;
    double im;
};


Complex2 operator+(Complex2 lhs, Complex2 rhs) 
{
    return Complex2(lhs.re + rhs.re, lhs.im + rhs.im);
}
Run Code Online (Sandbox Code Playgroud)

复杂.cpp:

#include "Complex.h"

Complex operator+(Complex lhs, Complex rhs) 
{
    return Complex(lhs.re + rhs.re, lhs.im + rhs.im);
}
Run Code Online (Sandbox Code Playgroud)

构建:

clang++ -O2 -c Complex.cpp
clang++ -O2 oper.cpp Complex.o -std=c++11
Run Code Online (Sandbox Code Playgroud)

结果如下所示:

Time=3265033
Sum:7.09575e+09
Time=1728941
Sum:6.72663e+09
Time=1705123
Sum:2.92692e+09
Run Code Online (Sandbox Code Playgroud)

如您所见,第一次大约是其他两个解决方案的 2 倍。这是因为Complex.cpp当代码在单独的翻译单元(单独编译)时,编译器无法内联代码