繁体   English   中英

inheritance真的不影响性能吗?

[英]Does inheritance really not affect performance?

我在互联网上( 此处此处)发现 inheritance 不会影响 class 的性能。 我对此感到好奇,因为我一直在为渲染引擎编写一个矩阵模块,这个模块的速度对我来说非常重要。

在我写完之后:

  • 底座:通用矩阵class
  • 从基础派生:方形实现
  • 派生自派生:方阵的 3-dim 和 4-dim 实现

我决定测试它们并面临实例化的性能问题

所以主要的问题是:

  1. 在我的情况下,这些性能问题的原因是什么?为什么它们通常会发生?
  2. 在这种情况下,我应该忘记 inheritance 吗?

这就是这些类的一般外观:

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...
}


为了进行测试,我使用了这个

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";
}

性能问题

使用单个 class 初始化,没有问题 - 每个 class 几乎每次都在 5 微秒以下。 但后来我决定扩大初始化的数量,他们的几个麻烦发生了

我运行每个测试 100 次,长度为 500 的 arrays

1. Class 用默认构造函数初始化

原始结果

我刚刚测试了 arrays 的初始化

结果是(以微秒为单位的平均时间):

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

在这里我们已经可以看到巨大的不同

这是代码

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 用默认构造函数初始化和填充

原始结果

测试了 class 实例的 arrays 的初始化,然后用自定义矩阵填充它们

结果(以微秒为单位的平均时间):

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

代码

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. 用 class 实例填充向量

原始结果

将自定义矩阵推回向量

结果(以微秒为单位的平均时间):

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

代码

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;
}

如果你需要所有的源代码,你可以在这里查看matrix.hmatrix.cpp

inheritance真的不影响性能吗?

是的。 只要不涉及虚方法,Inheritance 就不会影响运行时性能。 (因为只有这样你才需要在运行时推断类型并调用相应的虚拟方法覆盖)。 实际上,如果您深入了解细节,您就会知道 c++ inheritance 大多只是 static 的事情,即在编译时完成。

在我的情况下,这些性能问题的原因是什么?为什么它们通常会发生?

启用优化后,这些似乎效果很好?

在这种情况下,我应该忘记 inheritance 吗?

在这种对性能敏感的情况下,您唯一需要做的就是避免使用虚拟方法。

与这个问题无关的东西。 我已经阅读了你的代码。 也许在 header 文件中实现您的模板会更好?

暂无
暂无

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

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