最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c++矩陣計算性能對比:Eigen和GPU解讀

 更新時間:2022年12月15日 14:55:01   作者:guotianqing  
這篇文章主要介紹了c++矩陣計算性能對比:Eigen和GPU解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

生成隨機矩陣

生成隨機矩陣有多種方式,直接了當?shù)姆绞绞鞘褂蔑@式循環(huán)的方式為矩陣的每個元素賦隨機值。

#include <iostream>
#include <random>

using namespace std;

// 生成隨機數(shù)
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()
{
?? ??? ?// 直接使用內(nèi)置的Random,產(chǎn)生均勻分布隨機矩陣
? ? MatrixXd m = MatrixXd::Random(3,3);
? ??
? ? // 也可以調(diào)用自定義的隨機數(shù)生成函數(shù)填充數(shù)據(jù)
? ? // MatrixXd m = MatrixXd::Zero(3,3).unaryExpr(std::bind(GenerateRandomRealValue));
? ? return m;
}

計算矩陣點積

使用顯式循環(huán)計算

直接上代碼:

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";

結(jié)果分析

經(jīng)過測試,得到以下結(jié)論:

  • 對于CPU上矩陣運算來說,使用Eigen遠遠優(yōu)于顯式循環(huán)(我只使用了單線程,你當然可以嘗試多線程,但程度復雜度會明顯上升)
  • 對于小規(guī)模矩陣來說,Eigen庫要快于GPU(數(shù)據(jù)在host和device之間的拷貝消耗了大量的時間)
  • 對于較大規(guī)模矩陣來說,GPU的優(yōu)勢才顯現(xiàn)出來(數(shù)據(jù)運算時間超過了拷貝耗時,運算量越大,GPU并行的優(yōu)勢也越明顯)

總之:

  • 絕對避免使用顯式循環(huán),使用Eigen庫
  • 對于一般的應用來說,使用Eigen庫足夠應付大多數(shù)場景,畢竟CPU機器要比GPU機器廉價且普遍
  • 對于涉及大量的矩陣運算,包括機器學習等,GPU才是真正的用武之地

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • C++實現(xiàn)T型插補詳解

    C++實現(xiàn)T型插補詳解

    這篇文章主要介紹了C++實現(xiàn)T型插補,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-10-10
  • visual studio2019的安裝以及使用圖文步驟詳解

    visual studio2019的安裝以及使用圖文步驟詳解

    這篇文章主要介紹了visual studio2019的安裝以及使用圖文步驟詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-03-03
  • C語言拓展實現(xiàn)Lua sleep函數(shù)

    C語言拓展實現(xiàn)Lua sleep函數(shù)

    這篇文章主要介紹了C語言拓展實現(xiàn)Lua sleep函數(shù),本文使用C語言寫出sleep函數(shù),編譯后在Lua中調(diào)用,需要的朋友可以參考下
    2015-04-04
  • C++深入探究用NULL來初始化空指針是否合適

    C++深入探究用NULL來初始化空指針是否合適

    在C++11新特性中,我們用nullptr來表示指針空值,這是為什么呢?好好地NULL為什么不繼續(xù)使用呢?說明在創(chuàng)造C++的大佬們一定發(fā)現(xiàn)了什么Bug,本篇我們就一起來討論一下吧
    2022-05-05
  • C++中memset函數(shù)用法詳解

    C++中memset函數(shù)用法詳解

    這篇文章主要介紹了C++中memset函數(shù)用法,結(jié)合實例形式詳細分析了memset函數(shù)的功能、使用方法與相關(guān)注意事項,需要的朋友可以參考下
    2016-06-06
  • 一文詳解C++子類函數(shù)為什么不能重載父類函數(shù)

    一文詳解C++子類函數(shù)為什么不能重載父類函數(shù)

    這篇文章主要介紹了一文詳解C++子類函數(shù)為什么不能重載父類函數(shù),文章圍繞主題展開詳細的內(nèi)容戒殺,具有一定的參考價值,需要的朋友可以參考一下
    2022-09-09
  • 動態(tài)數(shù)組C++實現(xiàn)方法(分享)

    動態(tài)數(shù)組C++實現(xiàn)方法(分享)

    下面小編就為大家?guī)硪黄獎討B(tài)數(shù)組C++實現(xiàn)方法(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • C語言實現(xiàn)騎士飛行棋

    C語言實現(xiàn)騎士飛行棋

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)騎士飛行棋,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • C語言實現(xiàn)高精度加法的示例代碼

    C語言實現(xiàn)高精度加法的示例代碼

    高精度的本質(zhì)是將數(shù)字以字符串的形式讀入,然后將每一位分別存放入int數(shù)組中,通過模擬每一位的運算過程,來實現(xiàn)最終的運算效果,下面我們就來看看如何通過C語言實現(xiàn)高精度加法吧
    2023-11-11
  • C++新特性詳細分析基于范圍的for循環(huán)

    C++新特性詳細分析基于范圍的for循環(huán)

    C++11這次的更新帶來了令很多C++程序員期待已久的for?range循環(huán),每次看到j(luò)avascript,?lua里的for?range,心想要是C++能有多好,心里別提多酸了。這次C++11不負眾望,再也不用羨慕別家人的for?range了。下面看下C++11的for循環(huán)的新用法
    2022-04-04

最新評論

正镶白旗| 石狮市| 巴林左旗| 会东县| 新巴尔虎左旗| 织金县| 舟曲县| 玉环县| 林甸县| 镶黄旗| 延津县| 聊城市| 兴业县| 柳河县| 米林县| 婺源县| 厦门市| 宣威市| 兖州市| 从化市| 巴林右旗| 南召县| 建宁县| 宁武县| 察雅县| 佛坪县| 天台县| 象州县| 彭泽县| 石景山区| 外汇| 乌鲁木齐县| 三都| 永修县| 舟山市| 利川市| 厦门市| 通许县| 丹寨县| 二连浩特市| 临城县|