Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么MATLAB/Octave用C++;在特征值问题中?_C++_Performance_Matlab_Blas_Gsl - Fatal编程技术网

C++ 为什么MATLAB/Octave用C++;在特征值问题中?

C++ 为什么MATLAB/Octave用C++;在特征值问题中?,c++,performance,matlab,blas,gsl,C++,Performance,Matlab,Blas,Gsl,我希望标题中的问题的答案是我在做蠢事 问题就在这里。我想计算一个实对称矩阵的所有特征值和特征向量。我在Matlab中实现代码(实际上,我使用八度表运行它),和C++,使用我将在下面提供这两种实现的完整代码 据我所知,GSL自带了自己的BLAS API实现(以下我称之为GSLCBLAS),为了使用这个库,我编译时使用了: g++ -O3 -lgsl -lgslcblas g++ -O3 -lgsl -lcblas -latlas -lm GSL建议使用另一种BLAS库,例如自优化库,以提高性能

我希望标题中的问题的答案是我在做蠢事

问题就在这里。我想计算一个实对称矩阵的所有特征值和特征向量。我在Matlab中实现代码(实际上,我使用八度表运行它),和C++,使用我将在下面提供这两种实现的完整代码

据我所知,GSL自带了自己的BLAS API实现(以下我称之为GSLCBLAS),为了使用这个库,我编译时使用了:

g++ -O3 -lgsl -lgslcblas
g++ -O3 -lgsl -lcblas -latlas -lm
GSL建议使用另一种BLAS库,例如自优化库,以提高性能。我正在运行Ubuntu12.04,并且已经从安装了ATLAS软件包。在本例中,我使用以下方法编译:

g++ -O3 -lgsl -lgslcblas
g++ -O3 -lgsl -lcblas -latlas -lm
对于这三种情况,我都用随机生成的矩阵进行了实验,矩阵大小为100到1000,步长为100。对于每种大小,我使用不同的矩阵执行10次特征分解,并平均所用的时间。结果如下:

性能上的差异是荒谬的。对于大小为1000的矩阵,倍频程在一秒内执行分解;GSLCBLAS和ATLAS大约需要25秒

我怀疑我可能错误地使用了ATLAS图书馆。欢迎任何解释;提前谢谢

关于代码的一些注释:

    在C++实现中,不需要做矩阵 对称,因为

  • 在倍频程中,行
    triu(A)+triu(A,1)
    强制矩阵对称

  • <> >如果您希望编译自己的Linux机器的C++代码,还需要添加标志<代码> -LRT ,因为<代码> CcLogyGETTime< /Cuff>函数.< /P>
  • 不幸的是,我不认为其他平台上存在
    clock\u gettime
    。考虑将其更改为<代码> GETTimeFATE/<代码> < /P>
倍频程码

K = 10;

fileID = fopen('octave_out.txt','w');

for N = 100:100:1000
    AverageTime = 0.0;

    for k = 1:K
        A = randn(N, N);
        A = triu(A) + triu(A, 1)';
        tic;
        eig(A);
        AverageTime = AverageTime + toc/K;
    end

    disp([num2str(N), " ", num2str(AverageTime), "\n"]);
    fprintf(fileID, '%d %f\n', N, AverageTime);
end

fclose(fileID);
#include <iostream>
#include <fstream>
#include <time.h>

#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_eigen.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_matrix.h>

int main()
{
    const int K = 10;

    gsl_rng * RandomNumberGenerator = gsl_rng_alloc(gsl_rng_default);
    gsl_rng_set(RandomNumberGenerator, 0);

    std::ofstream OutputFile("atlas.txt", std::ios::trunc);

    for (int N = 100; N <= 1000; N += 100)
    {
        gsl_matrix* A = gsl_matrix_alloc(N, N);
        gsl_eigen_symmv_workspace* EigendecompositionWorkspace = gsl_eigen_symmv_alloc(N);
        gsl_vector* Eigenvalues = gsl_vector_alloc(N);
        gsl_matrix* Eigenvectors = gsl_matrix_alloc(N, N);

        double AverageTime = 0.0;
        for (int k = 0; k < K; k++)
        {   
            for (int i = 0; i < N; i++)
            {
                for (int j = 0; j < N; j++)
                {
                    gsl_matrix_set(A, i, j, gsl_ran_gaussian(RandomNumberGenerator, 1.0));
                }
            }

            timespec start, end;
            clock_gettime(CLOCK_MONOTONIC_RAW, &start);

            gsl_eigen_symmv(A, Eigenvalues, Eigenvectors, EigendecompositionWorkspace);

            clock_gettime(CLOCK_MONOTONIC_RAW, &end);
            double TimeElapsed = (double) ((1e9*end.tv_sec + end.tv_nsec) - (1e9*start.tv_sec + start.tv_nsec))/1.0e9;
            AverageTime += TimeElapsed/K;
            std::cout << "N = " << N << ", k = " << k << ", Time = " << TimeElapsed << std::endl;
        }
        OutputFile << N << " " << AverageTime << std::endl;

        gsl_matrix_free(A);
        gsl_eigen_symmv_free(EigendecompositionWorkspace);
        gsl_vector_free(Eigenvalues);
        gsl_matrix_free(Eigenvectors);
    }

    return 0;
}
C++代码

K = 10;

fileID = fopen('octave_out.txt','w');

for N = 100:100:1000
    AverageTime = 0.0;

    for k = 1:K
        A = randn(N, N);
        A = triu(A) + triu(A, 1)';
        tic;
        eig(A);
        AverageTime = AverageTime + toc/K;
    end

    disp([num2str(N), " ", num2str(AverageTime), "\n"]);
    fprintf(fileID, '%d %f\n', N, AverageTime);
end

fclose(fileID);
#include <iostream>
#include <fstream>
#include <time.h>

#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_eigen.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_matrix.h>

int main()
{
    const int K = 10;

    gsl_rng * RandomNumberGenerator = gsl_rng_alloc(gsl_rng_default);
    gsl_rng_set(RandomNumberGenerator, 0);

    std::ofstream OutputFile("atlas.txt", std::ios::trunc);

    for (int N = 100; N <= 1000; N += 100)
    {
        gsl_matrix* A = gsl_matrix_alloc(N, N);
        gsl_eigen_symmv_workspace* EigendecompositionWorkspace = gsl_eigen_symmv_alloc(N);
        gsl_vector* Eigenvalues = gsl_vector_alloc(N);
        gsl_matrix* Eigenvectors = gsl_matrix_alloc(N, N);

        double AverageTime = 0.0;
        for (int k = 0; k < K; k++)
        {   
            for (int i = 0; i < N; i++)
            {
                for (int j = 0; j < N; j++)
                {
                    gsl_matrix_set(A, i, j, gsl_ran_gaussian(RandomNumberGenerator, 1.0));
                }
            }

            timespec start, end;
            clock_gettime(CLOCK_MONOTONIC_RAW, &start);

            gsl_eigen_symmv(A, Eigenvalues, Eigenvectors, EigendecompositionWorkspace);

            clock_gettime(CLOCK_MONOTONIC_RAW, &end);
            double TimeElapsed = (double) ((1e9*end.tv_sec + end.tv_nsec) - (1e9*start.tv_sec + start.tv_nsec))/1.0e9;
            AverageTime += TimeElapsed/K;
            std::cout << "N = " << N << ", k = " << k << ", Time = " << TimeElapsed << std::endl;
        }
        OutputFile << N << " " << AverageTime << std::endl;

        gsl_matrix_free(A);
        gsl_eigen_symmv_free(EigendecompositionWorkspace);
        gsl_vector_free(Eigenvalues);
        gsl_matrix_free(Eigenvectors);
    }

    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main()
{
常数int K=10;
gsl_rng*RandomNumberGenerator=gsl_rng_alloc(gsl_rng_默认值);
gsl_rng_集(随机数发生器,0);
std::of流输出文件(“atlas.txt”,std::ios::trunc);
对于(int N=100;N

在C++实现中,不需要做矩阵 对称,因为函数只使用 它

情况可能并非如此。在本报告中,声明:

int gsl_特征对称(gsl_矩阵*A,gsl_向量*eval,gsl_矩阵*evec,gsl_特征对称工作空间*w)

该函数计算实对称矩阵的特征值和特征向量 A。必须在w中提供适当大小的附加工作区。 A的对角线和下三角部分在碰撞过程中被破坏 计算,但不引用严格的上三角部分。 特征值存储在向量eval中,并且是无序的 相应的特征向量存储在矩阵的列中 例如,第一列中的特征向量对应于 第一个特征值。保证特征向量相互独立 正交并归一化为单位震级

你也需要在C++中应用类似的对称化操作,以便获得至少正确的结果,尽管你可以得到相同的性能。 在MATLAB方面,由于其多线程执行,特征值分解可能更快,如中所述:

内置多线程

线性代数和数值函数,如fft、\(mldivide)、eig、, svd和sort在MATLAB中是多线程的。多线程计算 自2008a发布以来,默认情况下在MATLAB中处于启用状态 函数在同一时间内自动在多个计算线程上执行 单个MATLAB会话,允许它们在 支持多核的机器。此外,映像中的许多功能 处理工具箱™ 是多线程的

为了测试MATLAB的单核性能,可以通过

文件>首选项>常规>多线程


77a或更新的< P > >我不同意前面的帖子。这不是线程问题,这是一个算法问题。Matlab、R和OcTavy的理由是用C++库来擦除的,因为它们的C++库使用了更复杂、更好的算法。如果你读八度页,你可以发现他们做了什么[1 ]:

特征值的计算过程分为几步,首先是Hessenberg分解,然后是Schur分解,从中可以看出特征值。如果需要,可通过进一步操作Schur分解来计算特征向量

解决特征值/特征向量问题是非常重要的。事实上,这是“C中的数字配方”中为数不多的建议您不要自己实现的事情之一。(p461)。GSL通常很慢,这是我最初的反应。ALGLIB的标准实现也很慢(我得到了大约12秒!):

#包括
#包括
#包括
#包括
使用std::cout;
使用std::setw;
使用std::endl;
const int VERBOSE=false;
int main(int argc,字符**argv)
{
int size=0;
如果(argc!=2){

cout我也遇到过这个问题。真正的原因是matlab中的eig()没有计算特征向量,但上面的C版本代码会计算。所花费的时间差异可能大于一个数量级,如下图所示。因此比较不公平

在Matlab中,根据返回值的不同,调用的实际函数会有所不同。要强制计算特征向量,应使用(参见下面的代码)

计算特征值问题的实际时间在很大程度上取决于矩阵的性质和期望的结果,例如

  • 真实的还是复杂的