【问题标题】:Efficient coding with memory management使用内存管理进行高效编码
【发布时间】:2015-12-27 20:27:01
【问题描述】:

我最近从 matlab 切换到 c++ 以更快地运行模拟,但它仍然运行缓慢。我非常肯定在内存使用方面还有很多需要改进的地方。

考虑以下代码,它显示了我在模拟中使用的两个数组/向量声明的示例。

一个具有已知的固定长度 (array01),另一个具有未知长度 (array02),在运行期间会发生变化。

这里的问题是在内存使用和性能方面声明变量(对于两种数组类型)的最佳/正确/有效方式是什么。

# include <iostream>
# include <vector>
# include <ctime>
# include <algorithm>
using namespace std;

const int n = 1000;
const int m= 100000;
int main()
{
    srand((unsigned)time(NULL));
    vector <double> array02;
    vector <vector<double>> Array01(n,m);
    for (unsigned int i=0; i<n; i++)
    {
        for (unsigned int j=0; j<m;j++)
        {
             array02.clear();
             rr = rand() % 10;
             for (unsigned int l = 0 ; l<rr <l++)
             {
                  array02.pushback(l);
             }
             // perform some calculation with array01 and array02
         }           
     }
}

【问题讨论】:

  • reserve() 当您对所需的总大小有相当精确的估计时才有意义。在这种情况下,我认为您知道 size.so,vector.reserve() 应该有助于加快速度搞事情。
  • 在对需要优化的内容进行任何推测之前,先分析您的代码。顺便说一句,静态数组就足够了。
  • 我会先分析代码。
  • en.wikipedia.org/wiki/Profiling_(computer_programming)。您的开发环境应该有一个内置的分析器。这是遇到性能问题时必备的工具。
  • @jarhead,分析器:stackoverflow.com/questions/67554/…。但是您的代码不会很快,因为它平均执行十亿次操作。您应该研究降低代码算法复杂性的可能性。此外,rand() 函数非常慢且不够随机,请参阅stackoverflow.com/a/31091422/1915854

标签: c++ memory-management


【解决方案1】:

首先不要试图重新发明轮子 :) 尝试使用一些高度优化的数值库,例如

  • Intel MKL(适用于 Intel 和兼容处理器的最快和最常用的数学库)
  • LAPACK++(高性能线性代数库)
  • Boost(不仅是数值,而且几乎可以解决任何问题)

第二:如果您需要一个非常简单的程序的矩阵,请使用vector[i + width * j] 表示法。它更快,因为您节省了额外的内存分配。

您的示例没有事件编译。我试着改写一下:

#include <vector>
#include <ctime>

int main()
{
    const int rowCount = 1000;
    const int columnCount = 1000;

    srand(time(nullptr));

    // Declare matrix
    std::vector<double> matrix;

    // Preallocate elemts (faster insertion later)
    matrix.reserve(rowCount * columnCount);

    // Insert elements
    for (size_t i = 0; i < rowCount * columnCount; ++i) {
        matrix.push_back(rand() % 10);
    }

    // perform some calculation with matrix
    // For example this is a matrix element at matrix[1, 3]:
    double element_1_3 = matrix[3 + 1 * rowCount];

    return EXIT_SUCCESS;
}

现在速度取决于rand()(很慢)。

【讨论】:

    【解决方案2】:

    正如人们所说:

    • 矩阵首选一维数组而不是二维数组。
    • 不要重新发明轮子,使用现有的库:从您的代码来看,我认为Eigen library 是最适合您的套件。它还生成了非常非常优化的代码,因为它尽可能使用 C++ 模板静态计算。

    【讨论】:

      【解决方案3】:

      您应该考虑使用void resize(unsigned width, unsigned height) 成员函数、double get(unsigned i, unsigned j) 内联成员函数和/或 double&amp; at(unsigned i, unsigned j) 内联成员函数定义自己的 Matrix(两者都给出 Mi,j 元素)。矩阵内部数据可以是一维数组或双精度向量。使用向量组成的向量(大小都相同)并不是表示矩阵的最佳(或最快)方式。

      class Matrix {
         std::vector<double> data;
         unsigned width, height;
      public:
         Matrix() : data(), width(0), height(0) {};
         ~Matrix() = default;
         /// etc..., see rule of five
         void resize(unsigned w, unsigned h) {
            data.resize(w*h);
            width = w; height = h;
         }
         double get(unsigned i, unsigned j) const { 
            assert(i<width && j<height);
            return data[i*width+j];
         }
         double& at(unsigned i, unsigned j)  { 
            assert(i<width && j<height);
            return data[i*width+j];
         }
      }; // end class Matrix
      

      另请阅读rule of five

      你也可以试试scilab(它是免费软件)。它类似于 Matlab,可能有不同的性能。不要忘记使用最新版本。

      顺便说一句,现有大量的 C++ 数值库处理矩阵。考虑使用其中之一。如果性能至关重要,请不要忘记在调试代码后让编译器优化代码。

      假设您使用的是 Linux(我建议使用 Linux 进行数值计算;大多数超级计算机运行 Linux 很重要),在调试阶段使用 g++ -std=c++11 -Wall -Wextra -g 编译,然后在基准测试期间使用 g++ -std=c++11 -Wall -Wextra -mtune=native -O3。不要忘记profile,并记住过早的优化是邪恶的(你首先需要让你的程序正确)。

      您甚至可能会花费数周、数月甚至数年的时间来使用 OpenMPOpenCLMPIpthreadsstd::thread 等技术(对于 parallelization)(这很难您需要数年才能掌握的主题)。

      如果您的矩阵很大,和/或具有其他属性(sparsetriangularsymmetric 等...),则需要掌握许多数学和计算机科学知识来提高性能。你可以在这方面获得博士学位,并在这个主题上度过你的一生。所以去你的大学图书馆阅读一些关于numerical analysislinear algebra的书。

      对于随机数C++11 给你&lt;random&gt;;顺便说一句,使用 C++11 或 C++14,而不是某些早期版本的 C++。

      还可以阅读 http://floating-point-gui.de/ 和一本关于 C++ programming 的好书。

      PS。我没有声称在数值计算方面有任何特定的专业知识。我更喜欢符号计算。

      【讨论】:

      • Matrix 类在哪里? :O
      • OP 需要定义它。
      • @BasileStarynkevitch,我使用 Visual Studio Express 2010,使用 Windows 7。我不熟悉你提到的一些术语,你介意写一个你解释的例子吗?跨度>
      • 不,我没有时间(这可能意味着要写很多页)。这意味着教你很多东西。去你的大学图书馆,有很多关于这个主题的书,我没有特别的专业知识。
      • @HappyCoder,我不明白你的问题
      猜你喜欢
      • 2013-03-28
      • 1970-01-01
      • 2011-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多