CUBLAS库入门教程(从环境配置讲起)

news2024/10/7 20:25:03

文章目录

  • 前言
  • 一、搭建环境
  • 二、简单介绍
  • 三、 具体例子
  • 四、疑问


前言

CUBLAS库是NVIDIA CUDA用于线性代数计算的库。使用CUBLAS库的原因是我不想去直接写核函数。
(当然,你还是得学习核函数该怎么写。但是人家写好的肯定比我自己写的更准确!)


一、搭建环境

  1. 安装CUDA库,具体可以看我上一篇文章:在C++项目中集成CUDA程序加速(从环境配置讲起)
  2. 如果你是装在默认路径下,那么 CUBLAS库的头文件就在:C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.0\include 路径下面,以cublas开头的.h文件。
  3. 所以,还是按照步骤1的文章进行环境配置,然后只需要多在添加依赖项中增加一个cublas.lib就可以了。

二、简单介绍

  1. CUBLAS Introdution 是官方文档。(全英文的,还有不少数学公式。大家有不理解的可以直接留言区问相关API,我们一起讨论学习。)
  2. CUBLAS Samples 是官方示例,所有API都有。
  3. 对于API名称,都是cublasl<t>...,其中有下述类型选择:
    在这里插入图片描述
  4. CUBLAS库的矩阵是列向量的,跟glm一致。
  5. CUBLAS对于矩阵或者向量的index是从1开始的。所以,如果有函数的返回结果是个index(比如查找矩阵中的最大值),记得要index - 1才是我们要的。

三、 具体例子

下面我以矩阵与向量相乘的函数进行举例,看看是怎么用的。

  1. 首先,通过查找官方文档,知道是如下的函数:
cublasStatus_t cublasDgemv(cublasHandle_t handle, cublasOperation_t trans,
                           int m, int n,
                           const double          *alpha,
                           const double          *A, int lda,
                           const double          *x, int incx,
                           const double          *beta,
                           double          *y, int incy)
/*
* handle		: CUBLAS的句柄,用以管理CUBLAS库的上下文和资源
* CUBLAS_OP_N	: 指定矩阵操作模式。CUBLAS_OP_N代表正常模式(列向量);CUBLAS_OP_T代表转置模式(行向量)
* m				: 矩阵A的行数
* n				: 矩阵A的列数
* alpha			: 与矩阵A相乘的标量
* A				: 指向存储在device上面的矩阵数据指针
* lda			: 矩阵的列数,代表矩阵在内存中的存储方式
* x				: 向量X
* incx			: 向量x中相邻两个元素的index间隔,一般为1
* beta			: 与向量y相乘的标量
* y				: 向量y
* incy			: 向量y中相邻两个元素的index间隔,一般为1
*/

具体计算公式如下:
这是具体的计算公式

  1. 如果我们只是想计算矩阵和向量相乘,那么我们只需要令 α = 1.0, β = 0.0,然后传入我们要的Ax就行了。
  2. 最后,具体代码如下:
/// MyCublas.cuh

#pragma once

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "cublas_v2.h"

extern "C" void MatrixMulVectorCublas(
	const double* matrix, const int row, const int col, 
	const double* vector, double* result
);
/// MyCublas.cu

#include "MyCublas.cuh"
#include "CublasUtility.h"

void MatrixMulVectorCublas(
	const double* matrix, const int row, const int col,
	const double* vector, double* result)
{
	// 1. 初始化句柄
	cublasHandle_t handle;
	CUBLAS_CHECK(cublasCreate(&handle));

	// 2. 分配内存
	double* dev_matrix = NULL;
	double* dev_vector = NULL;
	CUDA_CHECK(cudaMalloc((void**)&dev_matrix, sizeof(double) * row * col));
	CUDA_CHECK(cudaMalloc((void**)&dev_vector, sizeof(double) * row));

	CUDA_CHECK(cudaMemcpy(dev_matrix, matrix, sizeof(double) * row * col, cudaMemcpyHostToDevice));
	CUDA_CHECK(cudaMemcpy(dev_vector, vector, sizeof(double) * row, cudaMemcpyHostToDevice));

	// 3. 执行矩阵乘法
	double* dev_result = NULL;
	CUDA_CHECK(cudaMalloc((void**)&dev_result, sizeof(double) * col));
	CUDA_CHECK(cudaMemset(dev_result, 0, sizeof(double) * col));

	const double alpha = 1.0;
	const double beta = 0.0;

	CUBLAS_CHECK(cublasDgemv(handle, CUBLAS_OP_N, row, col, &alpha, dev_matrix, col, dev_vector, 1, &beta, dev_result, 1));

	CUDA_CHECK(cudaMemcpy(result, dev_result, sizeof(double) * col, cudaMemcpyDeviceToHost));

	// 4. 释放内存
	CUDA_CHECK(cudaFree(dev_matrix));
	CUDA_CHECK(cudaFree(dev_vector));
	CUDA_CHECK(cudaFree(dev_result));
	CUBLAS_CHECK(cublasDestroy(handle));

}
/// CublasUtility.h

#pragma once
#include <string>
#include <stdexcept>
// CUDA API error checking
#define CUDA_CHECK(err)                                                                            \
    do {                                                                                           \
        cudaError_t err_ = (err);                                                                  \
        if (err_ != cudaSuccess) {                                                                 \
            std::printf("CUDA error %d at %s:%d\n", err_, __FILE__, __LINE__);                     \
            throw std::runtime_error("CUDA error");                                                \
        }                                                                                          \
    } while (0)

// cublas API error checking
#define CUBLAS_CHECK(err)                                                                          \
    do {                                                                                           \
        cublasStatus_t err_ = (err);                                                               \
        if (err_ != CUBLAS_STATUS_SUCCESS) {                                                       \
            std::printf("cublas error %d at %s:%d\n", err_, __FILE__, __LINE__);                   \
            throw std::runtime_error("cublas error");                                              \
        }                                                                                          \
    } while (0)

/// main.cpp

#include "MyCublas.cuh"

#include <iostream>

int main()
{
    double matrix[12] = { 1.0, 2.0, 3.0, 4.0,
                    5.0, 6.0, 7.0, 8.0,
                    9.0, 10.0, 11.0, 12.0};

    double vector[4] = { 1.0, 2.0, 3.0};

    double result[4] = { 0.0 };

    MatrixMulVectorCublas(matrix, 3, 4, vector, result);

    for (int i = 0; i < 4; ++i)
    {
        std::cout << result[i] << ", ";
    }
	return 0;
}

四、疑问

对于上述代码,我还有以下的疑问:

  1. 我在运行下面这句的时候,VS显示我的进程内存会到2.2GB左右,难道真的需要这么大吗?
CUBLAS_CHECK(cublasCreate(&handle));
  1. 上述代码运行的结果是:38, 44, 50, 0。但是实际结果应该是:38, 44, 50, 56。查了很久还是没差出来为什么。希望有细心的小伙伴帮我检查一下!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/956687.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

利用MarkovJunior方法生成迷宫和图形的MATLAB演示[迷宫生成、贪吃蛇、地图生成、图案生成]

利用MarkovJunior方法生成迷宫和图形的MATLAB演示[迷宫生成、贪吃蛇、地图生成、图案生成] 0 前言1 介绍MarkovJunior2 迷宫生成2.1 深度优先迷宫生成2.2 广度优先迷宫生成 3 其它生成图案3.1 地牢地图3.2 贪吃蛇3.3 植物花 惯例声明&#xff1a;本人没有相关的工程应用经验&am…

Python爬虫抓取经过JS加密的API数据的实现步骤

随着互联网的快速发展&#xff0c;越来越多的网站和应用程序提供了API接口&#xff0c;方便开发者获取数据。然而&#xff0c;为了保护数据的安全性和防止漏洞&#xff0c;一些API接口采用了JS加密技术这种加密技术使得数据在传输过程中更加安全&#xff0c;但也给爬虫开发带来…

客路旅行(KLOOK)面试(部分)(未完全解析)

一面 用过Chatgpt的哪个版本&#xff0c;了解Chatgpt版本之间的差异吗 什么是优雅部署&#xff1f;newBing: 服务启动时&#xff0c;检查依赖的组件或容器是否就绪&#xff0c;如果不就绪&#xff0c;等待或重试&#xff0c;直到就绪后再注册到服务中心&#xff0c;对外提供服…

AcWing 844. 走迷宫 (每日一题)

给定一个 nm 的二维整数数组&#xff0c;用来表示一个迷宫&#xff0c;数组中只包含 0 或 1&#xff0c;其中 0 表示可以走的路&#xff0c;1表示不可通过的墙壁。 最初&#xff0c;有一个人位于左上角 (1,1)处&#xff0c;已知该人每次可以向上、下、左、右任意一个方向移动一…

WIFI模块的工作原理及AP模式和STA模式的区别

WiFi模块的运作原理&#xff1a; WiFi模块通常由两大核心组件构成&#xff1a;无线芯片和微处理器。无线芯片专注于处理无线信号的传送与接收&#xff0c;而微处理器则全面管理和调控WiFi模块的各项功能。数据传输过程中&#xff0c;无线芯片利用无线电波进行信号的交互。通过…

网络安全社区与资源分享: 推荐网络安全社区、论坛、博客、培训资源等,帮助从业者拓展人脉和知识。

第一章&#xff1a;引言 在当今数字化的世界中&#xff0c;网络安全问题变得愈发突出。随着各种新型威胁的涌现&#xff0c;网络安全从业者面临着持续不断的挑战。然而&#xff0c;正是因为这些挑战&#xff0c;网络安全社区应运而生&#xff0c;成为从业者们互相交流、学习和…

C语言常见字符串和内存函数详解

字符串和内存函数 1. 前言2. 求字符串长度2.1 strlen 3. 长度不受限制的字符串函数3.1 strcpy3.2 strcat3.3 strcmp 4. 长度受限制的字符串函数4.1 strncpy4.2 strncat4.3 strncmp 5. 字符串查找5.1 strstr5.2 strtok 6. 错误信息报告6.1 strerror 7. 字符操作函数7.1 字符分类…

windows使用vim编辑文本powershell

windows使用vim编辑文本 1、安装 chocolatey 包 以管理员身份打开 PowerShell 进行安装 Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString(https://chocolatey.org/install.ps1))2、管理员身份打开 PowerShell 并使…

C++面试题(吴)-计算机网络部分(2)和常见设计模式

目录 1.网络部分 3.32 说说浏览器从输入 URL 到展现页面的全过程 3.33 简述 HTTP 和 HTTPS 的区别&#xff1f; 3.34 说说 HTTP 中的 referer 头的作用 3.35 说说 HTTP 的方法有哪些 3.36 简述 HTTP 1.0&#xff0c;1.1&#xff0c;2.0 的主要区别 3.37 说说 HTTP 常见的…

【笔记】PyCharm快捷键大全

PyCharm是一种Python集成开发环境&#xff08;IDE&#xff09;&#xff0c;由JetBrains公司开发。它被认为是Python开发中最强大、最流行的IDE之一。PyCharm具有完整的Python开发工具链&#xff0c;包括先进的代码编辑器、代码分析工具、集成的调试器、版本控制系统集成、自动化…

打车系统网约车系统开发支持APP公众号H5小程序版本源码

一、操作流程 二、业务模式 三、用户端 用户注册登录&#xff1a;未注册的手机号将自动创建账号 通过好友的邀请链接进行注册&#xff0c;将会绑定上下级关系 也可以注册的时候输入好友的邀请码&#xff0c;也可以绑定关系 用户充值&#xff1a; 用户下单支付时&#xff0c;可以…

Window11-Ubuntu双系统安装

一、制作Ubuntu系统盘 1.下载Ubuntu镜像源 阿里云开源镜像站&#xff1a;https://mirrors.aliyun.com/ubuntu-releases/ 清华大学开源软件镜像网站&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/ 选择想要的版本下载&#xff0c;我用的是20.04版本。 2…

环境异常总结

1.vue项目 npm run dev 运行时报错&#xff1a;webpack-dev-server --inline --progress --config build/webpack.dev.conf.js 不是内部或外部命令 原因&#xff1a;webpack-dev-server存在问题 解决方案&#xff1a;指定 webpack-dev-server 低版本号 方法&#xff1a; 删除 …

meethigher-Apache Poi 实现Excel多级联动下拉框

由于最近做的功能&#xff0c;需要将接口返回的数据列表&#xff0c;输出到excel中&#xff0c;以供后续导入&#xff0c;且网上现有的封装&#xff0c;使用起来都较为麻烦&#xff0c;故参考已有做法封装了工具类。 使用apache poi实现excel联动下拉框思路 创建隐藏单元格&a…

OceanBase 4.x改装:另一种全链路追踪的尝试

本文作者&#xff1a;夏克 OceanBase 社区文档贡献者&#xff0c;曾多次参与 OceanBase 技术征文比赛&#xff0c;获得优秀名次。从事金融行业核心系统设计开发工作多年&#xff0c;服务于某交易所子公司&#xff0c;现阶段负责国产数据库调研。 本文为 OceanBase 第七期技术征…

web端调用本地摄像头麦克风+WebRTC腾讯云,实现直播功能

目录 关于直播直播流程直播视频格式封装推流和拉流 获取摄像头和麦克风权限navigator.getUserMedia()MediaDevices.getUserMedia() WebRTC腾讯云快直播 关于直播 视频直播技术大全、直播架构、技术原理和实现思路方案整理 直播流程 视频采集端&#xff1a; 1、视频采集&#…

说说Flink双流join

分析&回答 Flink双流JOIN主要分为两大类 一类是基于原生State的Connect算子操作另一类是基于窗口的JOIN操作。其中基于窗口的JOIN可细分为window join和interval join两种。 基于原生State的Connect算子操作 实现原理&#xff1a;底层原理依赖Flink的State状态存储&…

深度学习推荐系统(三)NeuralCF及其在ml-1m电影数据集上的应用

深度学习推荐系统(三)NeuralCF及其在ml-1m电影数据集上的应用 在2016年&#xff0c; 随着微软的Deep Crossing&#xff0c; 谷歌的Wide&Deep以及FNN、PNN等一大批优秀的深度学习模型被提出&#xff0c; 推荐系统全面进入了深度学习时代&#xff0c; 时至今日&#xff0c; …

JavaDemo——使用LinkedHashMap实现简单的Cache

继承LinkedHashMap&#xff0c;合理使用构造方法public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder)和protected boolean removeEldestEntry(Map.Entry<K,V> eldest)方法就可以自己构建简单的Cache了&#xff1b; LinkedHashMap构造方法…

【三等奖方案】小样本数据分类任务赛题「复兴15号」团队解题思路

第十届CCF大数据与计算智能大赛&#xff08;2022 CCF BDCI&#xff09;已圆满结束。大赛官方竞赛平台DataFountain&#xff08;简称DF平台&#xff09;将陆续释出各赛题获奖队伍的方案思路。 本方案为【小样本数据分类任务】赛题的三等奖获奖方案&#xff0c;赛题地址&#xff…