C 和 C++ 的矩阵库评估和比较 Meschach、Cooperware 矩阵和 Blitz_sunnyxidian的博客-程序员秘密

原文网址:http://www.ibm.com/developerworks/cn/linux/other/matrix/index.html

本文假设读者对 C/C++ 有一定的了解并非常关注 C/C++ 本身没有矩阵功能。您可能在分析计量经济学的数据或模拟雨林。对于我来说,我正从事神经网络的研究而一两个矩阵可以大大简化神经网络的实现。虽然 C/C++ 包括可被看作矩阵(例如数组和标准库中的向量、列表和图)的容器,但是,真正 矩阵的容器将使手中的任务变得很容易。所以我们将介绍三个开放源代码库供您选择,它们不要求您从头开始构建矩阵,但的确让您使用矩阵库。如果您期望用从未见过的方法来使用它,那就太好了。

Meschach:用 C 的选择

对于用 C 编写代码的项目,Meschach(读作 me-shark)提供了例程,用于矩阵和向量的运算。它的优点是能在 Linux 和多数其它操作系统下编译,并且在版权保护下可公开获得,只要您作出例行的承认并报告错误。Meschach 可以解稠密或稀疏线性方程组、计算特征值和特征向量和解最小平方问题,另外还有其它功能。它为双精度数和复数提供了近 400 个函数。它提供的教程以说明性的小案例研究的形式介绍了这些函数。David Stewart 和 Zbigniew Leyk 通过一些主题的讨论来介绍 Meschach,这些主题包括超定方程组的广义的最小平方方程解答器(generalized least square equation solver for over-determined equations)和涉及稀疏矩阵的问题。他们的教程还包括三维矩阵和错误报告等稍稍高级的主题。

对象和类函数往往与代码关联,C 结构可能看起来有点神秘,所以 C 库往往不被作为可行的解决方案。但是作为对此的反击,这个库的组织很合理,所以不应不加思索地就舍弃它。在下载 Meschach 后过了一刻钟,我就可以制造、填充和显示矩阵了(在概念上等同于创建 Hello World!程序)。您可以参考一本名为“Meschach: Matrix Computations in C”的便宜的印刷品手册(请参阅本文末尾的 参考资料)。特别是测试程序“torture”,其中包括不少有益的线索。

矩阵可被容易地发送到文件或标准输出。Meschach 能计算快速傅立叶变换(Fast Fourier Transform)、提取列和行以及计算对称矩阵的特征值。您可以在矩阵中填充随机整数和复数。信不信由您,该库甚至还有矩阵相加的工具。Meschach 有一个返回在 [0,1) 之间的随机双精度数的函数,它是 Meschach 的一个特色,可用于简化明显的踏脚石程序的编写。虽然 Meschach 有一个用 1.0 填充矩阵的函数,但不幸的是,它没有用一个任意的双精度数填充矩阵的函数,也没有用随机双精度数填充矩阵的函数。不过,添加它们是容易的。


清单 1. 用一个任意的双精度数或随机双精度数来填充矩阵

MAT *m_fill( MAT *A, double x)
/* MAT *m_random_fill( MAT *A ) */
{
   int i, j;
   for ( i = 0; i < A->m; i++ ) for ( j = 0; j < A->n; j++ )
      { A->me[i][j] = x ; }
      /* { A->me[i][j] = m_random ; } */
   return A;
}


 

所以,正如我们所看到的,Meschach 代码可被容易地扩展,尽管在理想的世界中应该更加详细地注释代码。但是如果您正好在用 C 做计算工作并且要用到矩阵,那么这是很有用的库。


Cooperware 矩阵:基础知识

如果您要用 C++ 编写面向对象的代码并且您认为概念的清晰比速度更重要,那么 Harry Kuiper 的 Cooperware Matrix(CwMtx)能很好地运行。在这里讨论的三个矩阵库中,我觉得它的概念性体系结构最容易理解。在构造矩阵时,您直接使用:


清单 2. 构造矩阵

CWMatrix A( rows, columns ) ;


 

在这里考虑的三个库中,以三个评估性任务为标准,CwMtx 的性能最差,我们将在 速度部分详细地讨论。但是如果清晰比性能更重要(例如当您要确信您的数据被正确地处理),那么 CwMtx 是很好的选择。先使它正确,再使它快速。

CwMtx 中的矩阵包括向量和方阵,其中向量包括空间向量和四元数。一个矩阵可被映射到另一个矩阵、用某个元素来填充、转置和进行常见的数学运算。Kuiper 原先用 CwMtx 来模拟用离散的交互式状态机器构建的系统。除了必须的矩阵类,还有四元数类。对于明显问题的回答是,仅当 q = r + xi + yi + zi 时 q 才是四元数,其中 r 是实数,i 是 -1 的平方根,x、y 和 z 是复数。四元数可能把三维旋转的概念推广到四维(请参阅 参考资料,其中有四元数的参考资料的链接)。

CwMtx 没有内置的随机数生成器,也没有用随机元素填充矩阵的类函数。但是,它是免费的且它的发布受 GNU LGPL 许可证的保护,所以如果您愿意的话,您有创建这些(生成器和类函数)的自由。如果仅仅是用随机元素填充矩阵,那么以下代码是不错的和容易的选择。


清单 3. 用随机元素填充矩阵

#include <stdlib.h>
...
void random_fill( CWMatrix &M )
{
 int SIZE = M.GetRows() ;
 for ( int r=0; r<SIZE; r++ ) for ( int c=0; c<SIZE; c++ ) { M[r][c]= drand48(); }
}


 

这里的文档并不详细,但文档是清楚的并且组织得也很好。您能容易地找到类层次结构、构造函数、成员函数选项等信息。虽然没有教程,但您不会想念它;由于有了文档和测试程序,您并不需要它。


Blitz:和 Fortran 一样快?

Blitz 是另一个 C++ 库,它的发行受 GNU GPL 的保护,您可以用它来免费地创建对象。它支持 KAI、Intel、gcc、Metroworks 和 Cray 3.0.0.0 C++ 编译器,它还提供 n 维数组类,这些类可包括整数、浮点数、复数和用户定义的表现良好的类型。它的构造函数比 CwMtx 的构造函数更复杂,下面的示例证明了这一点:


清单 4. Blitz 构造函数

Array<double,2> A(4,7) ;


 

示例中创建了包含双精度数的秩为 2 的 4x7 数组。但是这样有点不清楚,所以 Blitz 使您把数组看作矩阵。还有,它没有实现许多矩阵函数。例如,它没有返回矩阵的特征值的函数。它也没有用随机双精度数来填充数组或矩阵的函数。但是,Blitz 确实有两个基本优点。

一个优点是它的广度。通过使用它自身的功能可以容易地实现和构造随机双精度数填充函数,如下面的示例所示:


清单 5. Blitz 中的随机双精度数填充函数

template <class Array, class Uniform>
void fill( Array &a, int size, Uniform &u )
{
   for ( int i=0; i<size; i++ )
      for ( int j=0; j<size; j++ )
         { a(i,j) = u.random() ; }
}


 

Blitz 的 Uniform 类提供返回在 [0,1) 间的双精度数的成员函数。它还提供三种访问数组元素的方法:标准索引、创建子数组和切片(slicing),切片能产生维数更小的数组片段的视图。Blitz 还处理标准计算器类型函数,所以数组可在标准输出上显示,而且可从文件中读入或发送到文件。Laplacian、坡度(gradient)和 Jacobian 运算符只是 Blitz 的模版(stencil)函数的三个示例。

Blitz 的另一个优点是它的速度。根据所用的编译器,C++ 的性能可以赶上 Fortran,而 Fortran 在科学和工程计算方面所表现的高性能是出名的。看一看下表中的比较,但是请阅读后面的 速度部分,其中分析了这些数据和基于这些数据的性能表现。

表 1. 在不同平台上的 Blitz 性能

 

平台 编译器 高速缓存外 高速缓存内
HPC-160 KAI C++ 100.2% 97.5%
Pentium II egcs 98.4% 79.6%
Cray T3E KAI C++ 95.7% 98.1%
Origin 2000 KAI C++ 88.1% 79.8%

 

Blitz 带有一本手册,格式是 HTML 和 Postscript,但不幸的是没有教程。然而,有不少说明性的代码,从中可以了解 Blitz 语法的细微差别。类的参考资料提供通常的信息。还有几个有用的邮件列表,已被归档,可供搜索(请参阅 参考资料)。


速度

库的评价标准有库的功能性资源、文档、库的教程质量、库的扩展难度等。库的评价标准还有性能和/或速度。但是,有时候比较它们是困难的,因为(我们的示例就是这种情况)它们并不是都用相同的语言来编写的,而且它们相同的自身功能也不多。在我们这里,三个库有足够的重复部分,这使我们能用三个比较简单但能说明问题的任务来比较它们的速度,我们将在下面三个示例中显示和讨论这些任务。


清单 6. 第 1 个任务

For ( d=2; d<7; d++)
   Construct 3 dxd matrices: A, B, C
   Start Clock: Do the following one million times:
      Fill A and B with 1.0s
      Let C = A + B
   Stop clock: Report elapsed time in seconds.


 

使用我们的库来实现并执行这个算法产生以下结果:

表 2. 第 1 个任务的结果

 

2x2 3x3 4x5 5x5 6x6
Blitz 0.40 0.48 0.62 0.75 0.91
CwMtx 2.64 3.57 4.58 5.60 6.60
Meschach 0.17 0.27 0.45 0.60 0.79

 

尽管 CwMtx 的体系结构易于理解,但不幸的是,它在这里的表现并不好。虽然 Blitz 的表现不如 Meschach,但是值得注意的是 Blitz 的性能大大超过了它的面向对象的对手 CwMtx。

如前所述,Meschach 和 Blitz 有提供随机双精度数的函数(随机数生成器),而 CwMtx 自身没有产生随机数的功能。考虑到随机化在某些基于矩阵的模拟中的关键作用,研究这些库在调用随机化的情况下的表现是有益的。


清单 7. 第 2 个任务

For ( d=2; d<7; d++)
   Construct 3 dxd matrices: A, B, C
   Start Clock: Do the following one million times:
      Fill A and B with random doubles (using library RNG, if any)
      Let C = A + B
   Stop clock: Report elapsed time in seconds.


 

我们的库的表现如下:

表 3. 第 2 个任务的结果

 

2x2 3x3 4x5 5x5 6x6
Blitz 0.87 1.71 2.83 4.34 6.13
CwMtx 3.67 5.87 8.59 11.93 15.61
Meschach 0.42 0.80 1.32 1.86 2.52

 

Blitz 的表现再次比 Meschach 差,但它的表现超过了它的面向对象的对手 CwMtx,而且这种差距令人吃惊。我们来看看第三个评价任务,以免您认为这是因为随机数生成器的性能有所不同。


清单 8. 第 3 个任务

For ( d=2; d<7; d++)
   Construct 3 dxd matrices: A, B, C
   Start Clock: Do the following one million times:
      Fill A and B with random doubles (using shared RNG)
      Let C = A + B
   Stop clock: Report elapsed time in seconds.


 

我们的库的性能排行榜与前面两个任务的相同:

表 4. 第 3 个任务的结果

 

2x2 3x3 4x5 5x5 6x6
Blitz 1.31 2.62 4.50 6.85 9.71
CwMtx 3.67 5.87 8.59 11.93 15.61
Meschach 1.17 2.45 4.28 6.63 9.40

 

如您所预料的那样,CwMtx 的性能排名没有改变。而且,Blitz 和 Meschach 的排名先后顺序也没有变。如果原始速度是决定性因素,那么这些库的排名现在已经很清楚。


在 Red Hat Linux 7.1 上安装和编译

为了您的方便,以下列出的是安装和编译这三个库的注解。下载的链接可在 参考资料中找到。


清单 9. Blitz

tar zxf blitz-0.5beta3.tar.gz
cd blitz-0.5beta3
./configure --with-cxx=gcc
make all
cp -a blitz/ /usr/local/include/ 
        ( or whatever you wish )
cp -a lib/ /usr/local/include/blitz/
        Compile with: g++ -O2 pgm.cpp -o pgm
      




清单 10. Meschach

unzip -q mesch12b.zip -d mesch12b
cd mesch12b
./configure
make basic
mkdir /usr/local/include/meschach 
        ( or whatever you wish )
cp *.h meschach.a /usr/local/include/meschach/
        Compile with: gcc -O2 pgm.c /usr/local/include/meschach/meschach.a -o pgm
      




清单 11. CwMtx

tar zxf cwmtx-0.3.0.tar.gz
cd cwmtx-0.3.0
        Open Makefile, and set INSTALL_DIR 
        to /usr/local/include/cwmtx 
        ( or whatever you wish )
        Execute: make install
        Compile with: g++ -O2 pgm.cpp -o pgm
      


 

 

我们已经了解了三个矩阵库的特色和它们本身的功能的详细信息。我们也看到了它们的一些功能缺点以及克服这些缺点的方法。我还为您提供了一些简单测试,这些测试所提供的原始的量化数据可能在您代码编写选择时对您有所帮助,但最终的决定要由您来作出,而且应该依据您的项目的自身特点以及在给出的环境中库的速度来作出决定。

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sunnyxidian/article/details/8916861

智能推荐

Spring的Ioc简单使用实例(含XML配置文件路径知识)_blant22000的博客-程序员秘密

1、引入spring.jar包。2、编写代码说明:这些类和XML配置文件都在同一个包“springtest”中接口类 TInterface.javapublic interface TInterface {public String getName();} 接口实现类 TImpl.javapublic class TImpl implements TInterface{

Android AVD无法启动问题解决_架构师训练营的博客-程序员秘密

1.The connection to adb is down, and a severe error has occured问题描述:The connection to adb is down, and a severe error has occured. [2012-06-21 12:56:17 - xmobile17] You must restart adb and Ec

java的foreach的使用、Array和ArrayList的区别以及各自的使用(java根本没有foreach,可以跟C#对比)java的foreach就是for,只是方式不一样_EP小良_007的博客-程序员秘密

java中foreach用法文章目录java中foreach用法java中foreach用法Array和ArrayList的区别以及使用区别Array和ArrayList的使用注意java中foreach用法java的foreach的使用(java根本没有foreach,或者说foreach就是 使用for来实现的,可以跟C#对比)java的foreach就是for,只是方式不一样java中可以通过foreach来遍历数组foreach语句格式:for(元素类型type 元素变量value

node.js中的path.resolve方法使用说明_nodejs path.resolve_Carina_best的博客-程序员秘密

方法说明:将参数 to 位置的字符解析到一个绝对路径里。语法:复制代码代码如下:path.resolve([from ...], to)由于该方法属于path模块,使用前需要引入path模块(var path= require(“path”) )接收参数:from                     源路径to

微信小程序 左右滑动删除事件_微信小程序右滑删除_呆鸟慢飞的博客-程序员秘密

微信小程序左右滑动删除事件效果图 &lt;scroll-view scroll-y enable-back-to-top style="height:{{ scrollHeight }}px" &gt; &lt;view&gt; &lt;block wx:for="{{ list }}" wx:for-item="item" wx:for-index="index" wx:key="index" &gt; &lt;view class="lis

python中的字符串是什么数据类型_python学习第九讲,python中的数据类型,字符串的使用与介绍..._weixin_39988677的博客-程序员秘密

python学习第九讲,python中的数据类型,字符串的使用与介绍一丶字符串1.字符串的定义字符串 就是 一串字符,是编程语言中表示文本的数据类型在 Python 中可以使用 一对双引号 " 或者 一对单引号 ' 定义一个字符串虽然可以使用 \" 或者 \' 做字符串的转义,但是在实际开发中:如果字符串内部需要使用 ",可以使用 ' 定义字符串如果字符串内部需要使用 ',可以使用 " 定义字符串...

随便推点

github中优秀得开源库_github 好看的seekba_zkq49099的博客-程序员秘密

Lottie   github地址:https://github.com/airbnb/lottie-android通过adobe affter effects制作动画,通过AE插件bodymovin到处json动画,给android以及ios使用,生成原生动画效果PreviewSeekBar   github地址:https://github.com/rubensousa/PreviewSeek...

解决jQuery一直引用错误(看这一篇就够了,没有用你来锤我)_jquery引入失败_贝贝才不是小淘气的博客-程序员秘密

在引入jQuery的时候显示:Uncaught ReferenceError: $ is not defined at response.jsp:14:9第一种:常规方法1.检查自己的路径有没有错误 &lt;script src="js/jquery-3.6.0.min.js"&gt;&lt;/script&gt;注意:上面引入jQuery的script标签一定要放在书写js代码标签的前面。2.可以在引入jQuery标签的下面加上这一段标签代码检验一下是否引入成功。&lt;script&

RGB2YUV420_izardMan的博客-程序员秘密

本文借鉴了别人的一些查表算法,改造成RGB2YUV420算法,计算速度更快,直接可用。typedef struct RGB{       unsigned char r;       unsigned char g;       unsigned char b;}RGB;        struct RGBin[IMGSIZE];//需要计算的原始数据

matlab复化梯形公式误差,数值分析复化梯形公式,复化Simpson公式MATLAB程序_李济斌GYM的博客-程序员秘密

分别用复化梯形公式、复化Simpson公式计算定积分分别验证结果(精确值I=4.006994)。复化梯形公式求定积分:function I=tquad(x,y)%复化梯形求积公式,其中,%x为向量,被积函数自变量的等距结点; %y为向量,被积函数在结点处的函数值; n=length(x);m=length(y);%积分自变量的结点数应与它的函数值的个数相同 h=(x(n)-x(1))/(n-1);...

mysql export db_DBexport最新版_程序员道道的博客-程序员秘密

DBexport最新版是一款十分出色的数据库数据导出工具,DBexport最新版界面美观大方,功能强劲实用,支持多数据源导出,支持图片种的数据库,支持扩展功能,支持自动生成配置文件,不必苦苦去寻找数据库配置文件,支持数据库连接测试,并且连接失败报告异常等。软件介绍DBexport(数据库数据导出工具),支持多数据源导出,目前已测试Oracle,MySQL,SQL_SERVER无明显BU...

[转] Gitlab 8.x runner安装与配置_weixin_30843605的博客-程序员秘密

【From】http://muchstudy.com/2018/07/13/Gitlab-8-x-runner%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/介绍  Gitlab 8.x之后默认集成了Gitlab CI,意味着支持了持续集成相关功能。每一次集成操作都需要对应的runner来跑代码构建、测试、发布等操作。Runner实际上就是...

推荐文章

热门文章

相关标签