c++矩阵计算性能对比:Eigen和GPU

这篇具有很好参考价值的文章主要介绍了c++矩阵计算性能对比:Eigen和GPU。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

生成随机矩阵

生成随机矩阵有多种方式,直接了当的方式是使用显式循环的方式为矩阵的每个元素赋随机值。

#include <iostream>
#include <random>

using namespace std;

// 生成随机数
double GenerateRandomRealValue()
{
    std::random_device rd;
    std::default_random_engine eng(rd());
    std::uniform_real_distribution<double> distr(1, 10);
    return distr(eng);
}

int main()
{
		// 3d矩阵
    double a[3][3];
    for (int i = 0; i < 3; ++i) {
        for (int j = 0;  j < 3; ++j) {
            a[i][j] = GenerateRandomRealValue();
        }
    }

    return 0;
}

另一种方式是使用Eigen库,它提供了矩阵运算的库。

生成随机矩阵:

#include "Eigen/Dense"
#include <functional>

using namespace std;
using namespace Eigen;

MatrixXd Generate2DMatrixByEigen()
{
		// 直接使用内置的Random,产生均匀分布随机矩阵
    MatrixXd m = MatrixXd::Random(3,3);
    
    // 也可以调用自定义的随机数生成函数填充数据
    // MatrixXd m = MatrixXd::Zero(3,3).unaryExpr(std::bind(GenerateRandomRealValue));
    return m;
}
计算矩阵点积

使用显式循环计算

直接上代码:


void CalcMatrixDotForLoop(const vector<vector<double>>& a, const vector<vector<double>>& b)
{
    std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
    if (a[0].size() != b.size()) {
        cout << "error:" << a.size() << "," << b[0].size() << endl;
        return;
    }

    vector<vector<double>> c;
    vector<double> c_row(b[0].size());
    for (int i = 0; i < a.size(); ++i) {
        for (int j = 0; j < b[0].size(); ++j) {
            for (int k = 0; k < b.size(); ++k) {
                c_row[j] += a[i][k] * b[k][j];
            }
        }
        c.emplace_back(c_row);
    }
    std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double, std::milli> time_span = t2 - t1;
    std::cout << "Loop takes " << time_span.count() << " ms\n";

    // cout << "matrix c:\n";
    // for (int i = 0; i < c.size(); ++i) {
    //     for (int j = 0; j < c[0].size(); ++j) {
    //         cout << c[i][j] << ",";
    //     }
    //     cout << endl;
    // }
}
使用Eigen库

代码:

void ModeEigen(const int a_row, const int a_col, const int b_row, const int b_col)
{
    std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
    auto c = a * b;
    std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double, std::milli> time_span = t2 - t1;
    std::cout << "Eigen takes " << time_span.count() << " ms\n";
    // cout << "matrix c:\n" << c << endl;
}
使用GPU

代码片断:

auto t_begin = std::chrono::high_resolution_clock::now();

t1 = std::chrono::high_resolution_clock::now();
cudaMalloc((void**)&da,size);
cudaMalloc((void**)&db,size);
cudaMalloc((void**)&dc,size);
t2 = std::chrono::high_resolution_clock::now();
time_span = t2 - t1;
std::cout << "GPU malloc takes " << time_span.count() << " ms\n";

t1 = std::chrono::high_resolution_clock::now();
cudaMemcpy(da,a,size,cudaMemcpyHostToDevice);
cudaMemcpy(db,b,size,cudaMemcpyHostToDevice);
t2 = std::chrono::high_resolution_clock::now();
time_span = t2 - t1;
std::cout << "cudaMemcpy takes " << time_span.count() << " ms\n";

t1 = std::chrono::high_resolution_clock::now();
dim3 dg(32,32);
dim3 dbs((n+dg.x-1)/dg.x,(n+dg.y-1)/dg.y);
mextix<<<dbs,dg>>>(da,db,dc,n);
t2 = std::chrono::high_resolution_clock::now();
time_span = t2 - t1;
std::cout << "gpu takes " << time_span.count() << " ms\n";

t1 = std::chrono::high_resolution_clock::now();
cudaMemcpy(c,dc,size,cudaMemcpyDeviceToHost);
t2 = std::chrono::high_resolution_clock::now();
time_span = t2 - t1;
std::cout << "cudaMemcpy back takes " << time_span.count() << " ms\n";

cudaFree(da);
cudaFree(db);
cudaFree(dc);

auto t_end = std::chrono::high_resolution_clock::now();
time_span = t_end - t_begin;
std::cout << "GPU total takes " << time_span.count() << " ms\n";
结果分析

经过测试,得到以下结论:

  • 对于CPU上矩阵运算来说,使用Eigen远远优于显式循环(我只使用了单线程,你当然可以尝试多线程,但程度复杂度会明显上升)
  • 对于小规模矩阵来说,Eigen库要快于GPU(数据在host和device之间的拷贝消耗了大量的时间)
  • 对于较大规模矩阵来说,GPU的优势才显现出来(数据运算时间超过了拷贝耗时,运算量越大,GPU并行的优势也越明显)

总之:文章来源地址https://www.toymoban.com/news/detail-520318.html

  • 绝对避免使用显式循环,使用Eigen库
  • 对于一般的应用来说,使用Eigen库足够应付大多数场景,毕竟CPU机器要比GPU机器廉价且普遍
  • 对于涉及大量的矩阵运算,包括机器学习等,GPU才是真正的用武之地

到了这里,关于c++矩阵计算性能对比:Eigen和GPU的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • c++ 的 Eigen库写 AX=XB的矩阵求解代码

    1.AX=XB的矩阵求解代码(3*3) 这里我们使用了Eigen库的 kroneckerProduct() 函数实现Kronecker积,使用 colPivHouseholderQr() 函数进行矩阵求解,得到X的值。 2.可以使用C++ Eigen库来求解线性方程组Ax=xB,其中A和B是两个已知的4x4矩阵。下面是一个使用Eigen库求解线性方程组的示例代码: 在上述

    2024年02月11日
    浏览(36)
  • Eigen 按行和按列计算矩阵的均值和标准差

      使用Eigen库实现矩阵按行和按列的平均值可以使用rowwise()和colwise()函数实现,具体代码如下: 要求标准差的话,把mean改成std即可。

    2024年02月02日
    浏览(34)
  • 【C++】开源:Eigen3矩阵与线性代数库配置使用

    😏 ★,° :.☆( ̄▽ ̄)/$: .°★ 😏 这篇文章主要介绍Eigen3线性代数模板库配置使用。 无专精则不能成,无涉猎则不能通。——梁启超 欢迎来到我的博客,一起学习,共同进步。 喜欢的朋友可以关注一下,下次更新不迷路🥞 项目Gitlab地址: https://gitlab.com/libeigen/eigen 官网:

    2024年02月14日
    浏览(32)
  • Eigen库的基本使用

    1.1.1 可以用重载后的 进行直接赋值,例如: 1.1.2 可以用Random(),在-1到1之间随机赋值 1.1.3 可以用Identity(),将第i行的第i个元素赋值为1,其余元素为0 1.1.4 可以用Zero(),将矩阵元素全赋值为0 1.2.1可以通过宏定义行数和列数来模拟动态矩阵 1.2.2 可以用Random(),在-1到1之间随机赋值

    2024年02月14日
    浏览(25)
  • Eigen库的基本使用说明(二)

     之前的文章中,简单的介绍了一些基本的操作,回归之前的内容可以参考一下链接: zEigen库的基本使用说明_每日亿学的博客-CSDN博客_eigen库  本章内容主要就是继续延伸Eigen库的使用内容也会实时进行更新,Eigen库在SLAM中使用广泛,需要对这个库有一定的熟悉。 首先最简单

    2023年04月22日
    浏览(25)
  • 用于计算机视觉的 OpenCV(C++ 与 Python)与 MATLAB之间的优缺点比较

    我们经常混淆我们的工具和我们的手艺。工具可以帮助你练习手艺,但它们并不能使你成为一名优秀的工匠。一个好工匠的口袋里有许多不同的工具,她会明智地使用适合工作的工具。她没有嫁给这些工具。她嫁给了她的手艺。 我经常被关于编程语言的战争逗乐。人们对哪一

    2024年02月13日
    浏览(31)
  • 音频处理库性能对比:计算mel频谱的速度哪个更快?

    音频信号处理在各种应用中都发挥着重要的作用,如语音识别、音乐信息检索、语音合成等。其中,Mel频谱是一种常用的频域特征表示方法,用于描述人类听觉系统对频率的敏感程度。 在深度学习音频领域,mel频谱是最常用的音频特征。在本文中,我们将对四个常用的音频处

    2023年04月25日
    浏览(35)
  • 并行计算框架Polars、Dask的数据处理性能对比

    在Pandas 2.0发布以后,我们发布过一些评测的文章,这次我们看看,除了Pandas以外,常用的两个都是为了大数据处理的并行数据框架的对比测试。 本文我们使用两个类似的脚本来执行提取、转换和加载(ETL)过程。 这两个脚本主要功能包括: 从两个parquet 文件中提取数据,对于小

    2024年02月16日
    浏览(32)
  • diffusion 和 gan 的优缺点对比

    train GAN 训练的网络是生成器和判别器,生成器用于生成图像,判别器辅助生成器的训练。 Diffusion 训练的噪声评估网络。 sample GAN 推理快,GAN的生成网络有维度变化。 Diffusion 推理慢,需要迭代更多次,推理过程图像尺寸不变。 训练难度 GAN 的训练可能是不稳定的,容易出现

    2024年01月25日
    浏览(40)
  • 矩阵分解及其Eigen实现

    主要是用来记录自己的学习过程,内容也主要来自于网上的各种资料,然后自己总结而来,参考的资料都以注明,感谢这些作者的分享。如果内容有误,请大家指点。 定义        将矩阵等价为两个矩阵 L L L 和 U U U 的乘积 ,其中 L L L 和 U U U 分别是单位下三角矩阵和上三角

    2024年02月03日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包