網站首頁 編程語言 正文
生成隨機矩陣
生成隨機矩陣有多種方式,直接了當的方式是使用顯式循環的方式為矩陣的每個元素賦隨機值。
#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并行的優勢也越明顯)
總之:
- 絕對避免使用顯式循環,使用Eigen庫
- 對于一般的應用來說,使用Eigen庫足夠應付大多數場景,畢竟CPU機器要比GPU機器廉價且普遍
- 對于涉及大量的矩陣運算,包括機器學習等,GPU才是真正的用武之地
總結
原文鏈接:https://blog.csdn.net/guotianqing/article/details/125810639
相關推薦
- 2022-10-16 Python使用random.shuffle()隨機打亂字典排序_python
- 2022-12-22 關于Python?ImportError:?No?module?named?通用解決方法_pytho
- 2023-07-28 el-table 給單元格設置背景色
- 2022-04-27 jquery+css實現移動端元素拖動排序_jquery
- 2022-10-24 C語言控制進程之進程等待詳解_C 語言
- 2022-01-07 event的srcelement和target
- 2022-06-11 MSSQL基本語法及實例操作語句_MsSql
- 2022-09-19 Redis實現事物以及鎖的方法_Redis
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支