为什么MATLAB在创建随机数时比C ++更快?

时间:2015-07-29 06:32:00

标签: c++ performance matlab

我一直在为我的项目使用MATLAB,我几乎从未有过使用C ++的经验。

我需要速度,我听说C ++比MATLAB更高效,更快。所以我尝试了这个:

我在MATLAB上使用rand(5000,5000)创建了一个随机数矩阵。

在C ++中,我初始化了一个为循环创建的2D向量,每个循环循环5000次并且每次都循环。 MATLAB的速度提高了4-5倍,所以我认为这是因为matlab并行执行矢量化代码,然后我使用parallel_for编写了C ++代码。这是代码:

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <fstream>
#include <ppl.h>
using namespace std;
using namespace concurrency;
int main();
{
    int a = 5000, b = 5000, j, k;
    vector< vector<int> > vec(a, vector<imt>(b));
    parallel_for(int(0), a, [&](int i) {
        for (j = 0; j <b; j++)
        {
            vec[i][j] = rand();
        }
    });
}

所以上面的代码比MATLAB rand(5000,5000)快25%左右但是C ++使用100%的CPU,而MATLAB使用30%的CPU。

所以我强迫MATLAB使用rand(5000,5000)运行3个MATLAB实例来使用所有CPU,并将所需时间除以3.它使MATLAB的速度是C ++的两倍。

我想知道我错过了什么?我知道这是一个很小的例子,但我需要一个答案,以确保将我的代码移植到C ++。

现状:

当我编写没有parallel_for的C ++代码时,我获得了相同CPU使用率的一半MATLAB速度。然而,给出答案的人说他们几乎是一样的。我不明白我错过了什么

这是优化菜单的快照 enter image description here

4 个答案:

答案 0 :(得分:2)

这可能不是答案,而是一个小小的提示。 由于vectors的使用,这种比较可能有点不公平。

这是我写的比较。两者都占据了四个可用线程中的一个的大约100%。在这两种情况下,我都会创建5000x5000个随机数,然后执行100次计时

<强> Matlab的

function stackoverflow

tic
for i=1:100
    A =rand(5000);
end
toc

运行时间:~27.9秒

<强> C ++

#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <ctime>

using namespace std;


int main(){

    int N = 5000;
    double ** A = new double*[N];
    for (int i=0;i<N;i++)
        A[i] = new double[N];


    srand(time(NULL));

    clock_t start = clock();
    for (int k=0;k<100;k++){
        for (int i=0;i<N;i++){
            for (int j=0;j<N;j++){
                A[i][j] = rand();
            }
        }
    }

    cout << "T="<< (clock()-start)/(double)(CLOCKS_PER_SEC/1000)<< "ms " << endl;

}

运行时间:~28.7秒

所以这两个例子的运行速度几乎相同。

答案 1 :(得分:1)

在查看@ sonystarmap的答案后,我添加了几种类型的容器:double*vector<double>vector<vector<double> >。我还添加了测试,其中“指针容器”是memset,因为vector初始化所有内存。

使用这些优化标志编译C ++代码:-O3 -march=native

结果:

Matlab:经过的时间是28.457788秒。

C ++:

T = 23844.2ms

T = 25161.5ms

T = 25154ms

T = 24197.3ms

T = 24235.2ms

T = 24166.1ms

我基本上找不到你提到的巨大收益。

#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <ctime>
#include <vector>
#include <cstring>

using namespace std;


int main(){

    const int N = 5000;

    {
        vector<double> A(N*N);

        srand(0);

        clock_t start = clock();
        for (int k=0;k<100;k++){
            for (int i=0;i<N;i++){
                for (int j=0;j<N;j++){
                    A[i*N+j] = rand();
                }
            }
        }

        cout << "T="<< (clock()-start)/(double)(CLOCKS_PER_SEC/1000)<< "ms " << endl;
    }

    {
        vector<vector<double> > A(N);
        for (int i=0;i<N;i++)
            A[i] = vector<double>(N);

        srand(0);

        clock_t start = clock();
        for (int k=0;k<100;k++){
            for (int i=0;i<N;i++){
                for (int j=0;j<N;j++){
                    A[i][j] = rand();
                }
            }
        }

        cout << "T="<< (clock()-start)/(double)(CLOCKS_PER_SEC/1000)<< "ms " << endl;
    }

    {
        double ** A = new double*[N];
        for (int i=0;i<N;i++)
            A[i] = new double[N];

        srand(0);

        clock_t start = clock();
        for (int k=0;k<100;k++){
            for (int i=0;i<N;i++){
                for (int j=0;j<N;j++){
                    A[i][j] = rand();
                }
            }
        }

        cout << "T="<< (clock()-start)/(double)(CLOCKS_PER_SEC/1000)<< "ms " << endl;
    }

    {
        double ** A = new double*[N];
        for (int i=0;i<N;i++) {
            A[i] = new double[N];
            memset(A[i], 0, sizeof(double) * N);
        }

        srand(0);

        clock_t start = clock();
        for (int k=0;k<100;k++){
            for (int i=0;i<N;i++){
                for (int j=0;j<N;j++){
                    A[i][j] = rand();
                }
            }
        }

        cout << "T="<< (clock()-start)/(double)(CLOCKS_PER_SEC/1000)<< "ms " << endl;
    }

    {
        double * A = new double[N * N];

        srand(0);

        clock_t start = clock();
        for (int k=0;k<100;k++){
            for (int i=0;i<N;i++){
                for (int j=0;j<N;j++){
                    A[i*N + j] = rand();
                }
            }
        }

        cout << "T="<< (clock()-start)/(double)(CLOCKS_PER_SEC/1000)<< "ms " << endl;
    }

    {
        double * A = new double[N * N];
        memset(A, 0, sizeof(double) * N * N);

        srand(0);

        clock_t start = clock();
        for (int k=0;k<100;k++){
            for (int i=0;i<N;i++){
                for (int j=0;j<N;j++){
                    A[i*N + j] = rand();
                }
            }
        }

        cout << "T="<< (clock()-start)/(double)(CLOCKS_PER_SEC/1000)<< "ms " << endl;
    }
}

答案 2 :(得分:1)

当您在Matlab中调用rand(5000,5000)时,Matlab通过调用Intel MKL库来执行命令,该库是用C / C ++编写的高度优化的库,带有许多手工编码的程序集。

MKL应该比任何简单的C ++实现都要快,但是Matlab调用外部库会产生开销。最终结果是,对于较小尺寸(例如小于1K)的随机数生成,纯C / C ++实现将更快,但是对于较大尺寸,Matlab将受益于超级优化的MKL。

答案 3 :(得分:0)

#include <vector>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cstring>

int main() {
  const int N = 5000;
  std::vector<int> A(N*N);
  srand(0);
  clock_t start = clock();
  for(int k = 0; k < 100; ++k){
    for(int i = 0; i < N * N; ++i) {
        A[i] = rand();
    }
  }
  std::cout << (clock()-start)/(double)(CLOCKS_PER_SEC/1000) << "ms" << "\n";
  return 0;
}

我的工作站上没有任何优化标志,从25-27秒到

的21秒
  

-O3 -g -Wall -ftree-vectorizer-verbose = 5 -msse -msse2 -msse3 -march = native -mtune = native -ffast-math