简体   繁体   English

inheritance真的不影响性能吗?

[英]Does inheritance really not affect performance?

I have found on the internet ( here and here ), that the inheritance doesn't affect the performance of the class.我在互联网上( 此处此处)发现 inheritance 不会影响 class 的性能。 I have become curious about that as I have been writing a matrices module for a render engine, and the speed of this module is very important for me.我对此感到好奇,因为我一直在为渲染引擎编写一个矩阵模块,这个模块的速度对我来说非常重要。

After I have written:在我写完之后:

  • Base: general matrix class底座:通用矩阵class
  • Derived from the base: square implementation从基础派生:方形实现
  • Derived from derived: 3-dim and 4-dim implementations of the square matrix派生自派生:方阵的 3-dim 和 4-dim 实现

I decided to test them and faced performance issues with instantiation我决定测试它们并面临实例化的性能问题

And so the main questions are:所以主要的问题是:

  1. What's the reason of these performance issues in my case and why may they happen in general?在我的情况下,这些性能问题的原因是什么?为什么它们通常会发生?
  2. Should I forget about inheritance in such cases?在这种情况下,我应该忘记 inheritance 吗?

This is how these classes look like in general:这就是这些类的一般外观:

template <class t>
class Matrix
{
protected:
    union {
        struct
        {
            unsigned int w, h;
        };
        struct
        {
            unsigned int n, m;
        };
    };

    /** Changes flow of accessing `v` array members */
    bool transposed;

    /** Matrix values array */
    t* v;

public:
    ~Matrix() {
        delete[] v;
    };
    Matrix() : v{}, transposed(false) {};

    // Copy
    Matrix(const Matrix<t>& m) : w(m.w), h(m.h), transposed(m.transposed) {
        v = new t[m.w * m.h];
        for (unsigned i = 0; i < m.g_length(); i++)
           v[i] = m.g_v()[i];
    };

    // Constructor from array
    Matrix(unsigned _w, unsigned _h, t _v[], bool _transposed = false) : w(_w), h(_h), transposed(_transposed) {
       v = new t[_w * _h];
       for (unsigned i = 0; i < _w * _h; i++)
           v[i] = _v[i];
    };

    /** Gets matrix array */
    inline t* g_v() const { return v; }
    /** Gets matrix values array size */
    inline unsigned g_length() const { return w * h; }

    // Other constructors, operators, and methods.
}



template<class t>
class SquareMatrix : public Matrix<t> {
public:
    SquareMatrix() : Matrix<t>() {};
    SquareMatrix(const Matrix<t>& m) : Matrix<t>(m) {};

    SquareMatrix(unsigned _s, t _v[], bool _transpose) : Matrix<t>(_s, _s, _v, _transpose) {};
    // Others...
}

template<class t>
class Matrix4 : public SquareMatrix<t> {
public:
    Matrix4() : SquareMatrix<t>() {};
    Matrix4(const Matrix<t>& m) : SquareMatrix<t>(m) {}

    Matrix4(t _v[16], bool _transpose) : SquareMatrix<t>(4, _v, _transpose) {};
    // Others...
}


To conduct tests I used this为了进行测试,我使用了这个

void test(std::ofstream& f, char delim, std::function<void(void)> callback) {
    auto t1 = std::chrono::high_resolution_clock::now();
    callback();
    auto t2 = std::chrono::high_resolution_clock::now();
    f << std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count() << delim;
    //std::cout << "test took " << std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count() << " microseconds\n";
}

Performance problems性能问题

With single class initialization, there're no problems - it goes under 5 microseconds almost every time for every class.使用单个 class 初始化,没有问题 - 每个 class 几乎每次都在 5 微秒以下。 But then I decided to scale up the number of initializations and their several troubles occurred但后来我决定扩大初始化的数量,他们的几个麻烦发生了

I ran every test 100 times, with arrays of length 500我运行每个测试 100 次,长度为 500 的 arrays

1. Class initialization with the default constructor 1. Class 用默认构造函数初始化

Raw results原始结果

I just tested the initialization of arrays我刚刚测试了 arrays 的初始化

The results were (avg time in microseconds):结果是(以微秒为单位的平均时间):

  • Matrix 25.19矩阵 25.19
  • SquareMatrix 40.37 (37.60% loss) SquareMatrix 40.37(损失 37.60%)
  • Matrix4 58.06 (30.47% loss from SquareMatrix) Matrix4 58.06(SquareMatrix 损失 30.47%)

And here we can already see a huge difference在这里我们已经可以看到巨大的不同

Here's the code这是代码

int main(int argc, char** argv)
{
    std::ofstream f("test.csv");
    f << "Matrix\t" << "SquareMatrix\t" << "Matrix4\n";

    for (int k = 0; k < 100; k++) {
        test(f, '\t', []() {
            Matrix<long double>* a = new Matrix<long double>[500];
            });

        test(f, '\t', []() {
            SquareMatrix<long double>* a = new SquareMatrix<long double>[500];
            });

        test(f, '\n', []() {
            Matrix4<long double>* a = new Matrix4<long double>[500];
            });
    }

    f.close();

    return 0;
}

2. Class initialization with default constructor and filling 2. Class 用默认构造函数初始化和填充

Raw results原始结果

Tested the initialization of arrays of class instances and filling them after with custom matrices测试了 class 实例的 arrays 的初始化,然后用自定义矩阵填充它们

The results (avg time in microseconds):结果(以微秒为单位的平均时间):

  • Matrix 402.8矩阵 402.8
  • SquareMatrix 475 (15.20% loss) SquareMatrix 475(15.20% 损失)
  • Matrix4 593.86 (20.01% loss from SquareMatrix) Matrix4 593.86(SquareMatrix 损失 20.01%)

Code代码

int main(int argc, char** argv)
{
    long double arr[16] = {
       1, 2, 3, 4,
       5, 6, 7, 8,
       9, 10, 11, 12,
       13, 14,15,16
    };

    std::ofstream f("test.csv");
    f << "Matrix\t" << "SquareMatrix\t" << "Matrix4\n";

    for (int k = 0; k < 100; k++) {
        test(f, '\t', [&arr]() {
            Matrix<long double>* a = new Matrix<long double>[500];
            for (int i = 0; i < 500; i++) 
                a[i] = Matrix<long double>(4, 4, arr);
            });

        test(f, '\t', [&arr]() {
            SquareMatrix<long double>* a = new SquareMatrix<long double>[500];
            for (int i = 0; i < 500; i++) 
                a[i] = SquareMatrix<long double>(4, arr);
            });

        test(f, '\n', [&arr]() {
            Matrix4<long double>* a = new Matrix4<long double>[500];
            for (int i = 0; i < 500; i++) 
                a[i] = Matrix4<long double>(arr);
            });
    }

    f.close();

    return 0;
}

3. Filling vector with class instances 3. 用 class 实例填充向量

Raw results原始结果

Pushed back custom matrices to vector将自定义矩阵推回向量

The results (avg time in microseconds):结果(以微秒为单位的平均时间):

  • Matrix 4498.1矩阵 4498.1
  • SquareMatrix 4693.93 (4.17% loss) SquareMatrix 4693.93(损失 4.17%)
  • Matrix4 4960.12 (5.37% loss from its SquareMatrix) Matrix4 4960.12(其 SquareMatrix 损失 5.37%)

Code代码

int main(int argc, char** argv)
{
    long double arr[16] = {
       1, 2, 3, 4,
       5, 6, 7, 8,
       9, 10, 11, 12,
       13, 14,15,16
    };

    std::ofstream f("test.csv");
    f << "Matrix\t" << "SquareMatrix\t" << "Matrix4\n";

    for (int k = 0; k < 100; k++) {
        test(f, '\t', [&arr]() {
            std::vector<Matrix<long double>> a = std::vector<Matrix<long double>>();
            for (int i = 0; i < 500; i++)
                a.push_back(Matrix<long double>(4, 4, arr));
            });

        test(f, '\t', [&arr]() {
            std::vector<SquareMatrix<long double>> a = std::vector<SquareMatrix<long double>>();
            for (int i = 0; i < 500; i++)
                a.push_back(SquareMatrix<long double>(4, arr));
            });

        test(f, '\n', [&arr]() {
            std::vector<Matrix4<long double>> a = std::vector<Matrix4<long double>>();
            for (int i = 0; i < 500; i++)
                a.push_back(Matrix4<long double>(arr));
            });
    }

    f.close();

    return 0;
}

If you need all the source code, you can look here into matrix.h and matrix.cpp如果你需要所有的源代码,你可以在这里查看matrix.hmatrix.cpp

Does inheritance really not affect performance? inheritance真的不影响性能吗?

Yes.是的。 Inheritance won't affect runtime performance as long as virtual method isn't involved.只要不涉及虚方法,Inheritance 就不会影响运行时性能。 (Cuz only then will you have to deduce the type at runtime and call corresponding virtual method override). (因为只有这样你才需要在运行时推断类型并调用相应的虚拟方法覆盖)。 In fact, if you have a sight into lower details, you will know that c++ inheritance is mostly just static things, that is, done at compilation time.实际上,如果您深入了解细节,您就会知道 c++ inheritance 大多只是 static 的事情,即在编译时完成。

What's the reason of these performance issues in my case and why may they happen in general?在我的情况下,这些性能问题的原因是什么?为什么它们通常会发生?

It seems these work well when optimization is enabled?启用优化后,这些似乎效果很好?

Should I forget about inheritance in such cases?在这种情况下,我应该忘记 inheritance 吗?

The only thing you need to do in such performance-sensitive cases is to avoid virtual method.在这种对性能敏感的情况下,您唯一需要做的就是避免使用虚拟方法。

Something not related to this question.与这个问题无关的东西。 I have read your code.我已经阅读了你的代码。 Perhaps it will be better to implement your templates in header file?也许在 header 文件中实现您的模板会更好?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM