CUBLAS矩阵乘法

2023-11-03

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

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

#define M 512
#define K 512
#define N 512

#define BLOCK_SIZE 32  //block size ,each thread to calucate each bloc

void initial(float *array, int size)
{
	for (int i = 0; i < size; i++)
	{
		array[i] = (float)(rand() % 10 + 1);
	}
}

void printMatrix(float *array, int row, int col)
{
	float *p = array;
	for (int y = 0; y < row; y++)
	{
		for (int x = 0; x < col; x++)
		{
			printf("%10lf", p[x]);
		}
		p = p + col;
		printf("\n");
	}
	return;
}

void  multiplicateMatrixOnHost(float *array_A, float *array_B, float *array_C, int M_p, int K_p, int N_p)
{
	for (int i = 0; i < M_p; i++)
	{
		for (int j = 0; j < N_p; j++)
		{
			float sum = 0;
			for (int k = 0; k < K_p; k++)
			{
				sum += array_A[i*K_p + k] * array_B[k*N_p + j];
			}
			array_C[i*N_p + j] = sum;
		}
	}
}

__global__ void multiplicateMatrixOnDevice(float *array_A, float *array_B, float *array_C, int M_p, int K_p, int N_p)
{
	int ix = threadIdx.x + blockDim.x*blockIdx.x;//row number
	int iy = threadIdx.y + blockDim.y*blockIdx.y;//col number

	if (ix < N_p && iy < M_p)
	{
		float sum = 0;
		for (int k = 0; k < K_p; k++)
		{
			sum += array_A[iy*K_p + k] * array_B[k*N_p + ix];
		}
		array_C[iy*N_p + ix] = sum;
	}
}

// Compute C = A * B
__global__ void matrixMultiplyShared(float *A, float *B, float *C,
	int numARows, int numAColumns, int numBRows, int numBColumns, int numCRows, int numCColumns)
{
	//@@ Insert code to implement matrix multiplication here
	//@@ You have to use shared memory for this MP

	__shared__ float sharedM[BLOCK_SIZE][BLOCK_SIZE];
	__shared__ float sharedN[BLOCK_SIZE][BLOCK_SIZE];

	int bx = blockIdx.x;
	int by = blockIdx.y;
	int tx = threadIdx.x;
	int ty = threadIdx.y;

	int row = by * BLOCK_SIZE + ty;
	int col = bx * BLOCK_SIZE + tx;

	float Csub = 0.0;

	for (int i = 0; i < (int)(ceil((float)numAColumns / BLOCK_SIZE)); i++)
	{
		if (i*BLOCK_SIZE + tx < numAColumns && row < numARows)
			sharedM[ty][tx] = A[row*numAColumns + i * BLOCK_SIZE + tx];
		else
			sharedM[ty][tx] = 0.0;

		if (i*BLOCK_SIZE + ty < numBRows && col < numBColumns)
			sharedN[ty][tx] = B[(i*BLOCK_SIZE + ty)*numBColumns + col];
		else
			sharedN[ty][tx] = 0.0;
		__syncthreads();

		for (int j = 0; j < BLOCK_SIZE; j++)
			Csub += sharedM[ty][j] * sharedN[j][tx];
		__syncthreads();
	}

	if (row < numCRows && col < numCColumns)
		C[row*numCColumns + col] = Csub;
}


int main(int argc, char **argv)
{
	clock_t start = 0, finish = 0;
	float time;

	int Axy = M * K;
	int Bxy = K * N;
	int Cxy = M * N;

	float *h_A, *h_B, *hostRef, *deviceRef;
	h_A = (float*)malloc(Axy * sizeof(float));
	h_B = (float*)malloc(Bxy * sizeof(float));

	int nBytes = M * N * sizeof(float);
	hostRef = (float*)malloc(Cxy * sizeof(float));
	deviceRef = (float*)malloc(Cxy * sizeof(float));

	initial(h_A, Axy);
	initial(h_B, Bxy);

	start = clock();
	multiplicateMatrixOnHost(h_A, h_B, hostRef, M, K, N);
	finish = clock();
	time = (float)(finish - start) / CLOCKS_PER_SEC;

	printf("\n");
	printf("------------------------------------------------------------------------------------\n");
	printf("Computing matrix product using multiplicateMatrixOnHost \n");
	printf("------------------------------------------------------------------------------------\n");

	printf("Matrix_hostRef: (%d×%d)  CPU运行时间为:%lfs\n", M, N, time);

	float *d_A, *d_B, *d_C;
	cudaMalloc((void**)&d_A, Axy * sizeof(float));
	cudaMalloc((void**)&d_B, Bxy * sizeof(float));
	cudaMalloc((void**)&d_C, Cxy * sizeof(float));

	cudaMemcpy(d_A, h_A, Axy * sizeof(float), cudaMemcpyHostToDevice);
	cudaMemcpy(d_B, h_B, Bxy * sizeof(float), cudaMemcpyHostToDevice);

	printf("\n\n");
	printf("------------------------------------------------------------------------------------\n");
	printf("Computing matrix product using multiplicateMatrixOnDevice \n");
	printf("------------------------------------------------------------------------------------\n");

    int dimx = 2;
    int dimy = 2;
    dim3 block(dimx, dimy);
    dim3 grid((M + block.x - 1) / block.x, (N + block.y - 1) / block.y);

    cudaEvent_t gpustart, gpustop;
    float elapsedTime = 0.0;
    cudaEventCreate(&gpustart);
    cudaEventCreate(&gpustop);
    cudaEventRecord(gpustart, 0);
    multiplicateMatrixOnDevice<<<grid,block>>> (d_A, d_B, d_C, M, K, N);
    cudaDeviceSynchronize();
    cudaEventRecord(gpustop, 0);
    cudaEventSynchronize(gpustop);

    cudaEventElapsedTime(&elapsedTime, gpustart, gpustop);
    cudaEventDestroy(gpustart);
    cudaEventDestroy(gpustop);

    cudaMemcpy(deviceRef, d_C, Cxy * sizeof(float), cudaMemcpyDeviceToHost);
    printf("Matrix_deviceRef: (%d×%d)  <<<(%d,%d),(%d,%d)>>>  GPU运行时间为:%fs\n", M, N, grid.x, grid.y, block.x, block.y, elapsedTime / 1000);

	elapsedTime = 0.0;
	cudaEventCreate(&gpustart);
	cudaEventCreate(&gpustop);
	cudaEventRecord(gpustart, 0);
	matrixMultiplyShared << < grid, block >> > (d_A, d_B, d_C, M, K, K, N, M, N);
	cudaDeviceSynchronize();
	cudaEventRecord(gpustop, 0);
	cudaEventSynchronize(gpustop);

	cudaEventElapsedTime(&elapsedTime, gpustart, gpustop);
	cudaEventDestroy(gpustart);
	cudaEventDestroy(gpustop);

	cudaMemcpy(deviceRef, d_C, Cxy * sizeof(float), cudaMemcpyDeviceToHost);
	printf("Matrix_deviceRef: (%d×%d)  <<<(%d,%d),(%d,%d)>>>  GPU运行时间为:%fs\n", M, N, grid.x, grid.y, block.x, block.y, elapsedTime / 1000);

    cublasStatus_t status;
    cublasHandle_t handle;
    cublasCreate(&handle);

    elapsedTime = 0.0;
    cudaEventCreate(&gpustart);
    cudaEventCreate(&gpustop);
    cudaEventRecord(gpustart, 0);

    float a = 1, b = 0;
    cublasSgemm(
        handle,
        CUBLAS_OP_T,   //矩阵A的属性参数,转置,按行优先
        CUBLAS_OP_T,   //矩阵B的属性参数,转置,按行优先
        M,          //矩阵A、C的行数
        N,          //矩阵B、C的列数
        K,          //A的列数,B的行数,此处也可为B_ROW,一样的
        &a,             //alpha的值
        d_A,            //左矩阵,为A
        K,          //A的leading dimension,此时选择转置,按行优先,则leading dimension为A的列数
        d_B,            //右矩阵,为B
        N,          //B的leading dimension,此时选择转置,按行优先,则leading dimension为B的列数
        &b,             //beta的值
        d_C,            //结果矩阵C
        M           //C的leading dimension,C矩阵一定按列优先,则leading dimension为C的行数
    );
    cudaMemcpy(deviceRef, d_C, Cxy * sizeof(float), cudaMemcpyDeviceToHost);
    cudaDeviceSynchronize();
    cudaEventRecord(gpustop, 0);
    cudaEventSynchronize(gpustop);

    cudaEventElapsedTime(&elapsedTime, gpustart, gpustop);
    cudaEventDestroy(gpustart);
    cudaEventDestroy(gpustop);

    printf("Matrix_deviceRef: (%d×%d)  <<<(%d,%d),(%d,%d)>>>  GPU运行时间为:%fs\n", M, N, grid.x, grid.y, block.x, block.y, elapsedTime / 1000);

	cudaFree(d_A);
	cudaFree(d_B);
	cudaFree(d_C);

	free(h_A);
	free(h_B);
	free(hostRef);
	free(deviceRef);

	cudaDeviceReset();

	return (0);
}

运行结果:

------------------------------------------------------------------------------------
Computing matrix product using multiplicateMatrixOnHost
------------------------------------------------------------------------------------
Matrix_hostRef: (512×512)  CPU运行时间为:0.065000s


------------------------------------------------------------------------------------
Computing matrix product using multiplicateMatrixOnDevice
------------------------------------------------------------------------------------
Matrix_deviceRef: (512×512)  <<<(256,256),(2,2)>>>  GPU运行时间为:0.002266s
Matrix_deviceRef: (512×512)  <<<(256,256),(2,2)>>>  GPU运行时间为:0.001658s
Matrix_deviceRef: (512×512)  <<<(256,256),(2,2)>>>  GPU运行时间为:0.000205s
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CUBLAS矩阵乘法 的相关文章

  • 如何在 CUDA 中执行多个矩阵乘法?

    我有一个方阵数组int M 10 以便M i 定位第一个元素i th 矩阵 我想将所有矩阵相乘M i 通过另一个矩阵N 这样我就收到了方阵数组int P 10 作为输出 我看到有不同的可能性 分配不同元素的计算M i 到不同的线程 例如 我
  • Yocto for Nvidia Jetson 由于 GCC 7 而失败 - 无法计算目标文件的后缀

    我正在尝试将 Yocto 与 meta tegra 一起使用 https github com madisongh meta tegra https github com madisongh meta tegra 为 Nvidia Jets
  • 尝试构建我的 CUDA 程序时出现错误 MSB4062

    当我尝试构建我的第一个 GPU 程序时 出现以下错误 有什么建议可能会出什么问题吗 错误 1 错误 MSB4062 Nvda Build CudaTasks SanitizePaths 任务 无法从程序集 C Program 加载 文件 M
  • 在 cudaFree() 之前需要 cudaDeviceSynchronize() 吗?

    CUDA 版本 10 1 帕斯卡 GPU 所有命令都发送到默认流 void ptr cudaMalloc ptr launch kernel lt lt lt gt gt gt ptr cudaDeviceSynchronize Is th
  • cuda中内核的并行执行

    可以说我有三个全局数组 它们已使用 cudaMemcpy 复制到 GPU 中 但 c 中的这些全局数组尚未使用 cudaHostAlloc 分配 以便分配页面锁定的内存 而不是简单的全局分配 int a 100 b 100 c 100 cu
  • VS 程序在调试模式下崩溃,但在发布模式下不崩溃?

    我正在 VS 2012 中运行以下程序来尝试 Thrust 函数查找 include cuda runtime h include device launch parameters h include
  • 具有 Cuda Thrust 的多个 GPU?

    如何将 Thrust 与多个 GPU 一起使用 这只是使用 cudaSetDevice deviceId 的问题吗 然后运行相关的 Thrust 代码 使用 CUDA 4 0 或更高版本 cudaSetDevice deviceId 接下来
  • CUDA NSight 未随 Windows 8 上的 CUDA 5.0 安装文件一起安装? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 据我所知 Nvidia 网站上没有 Nsight Eclipse 的下载链接 它说它将由 CUDA 5 安装本机安装 但并没有随CUDA安装一起安装
  • CUDA计算能力2.0。全局内存访问模式

    CUDA 计算能力 2 0 Fermi 全局内存访问通过 768 KB L2 缓存进行 看起来 开发人员不再关心全局内存库 但全局内存仍然非常慢 因此正确的访问模式很重要 现在的重点是尽可能多地使用 重用 L2 我的问题是 如何 我将感谢一
  • OpenCV 2.4.3rc 和 CUDA 4.2:“OpenCV 错误:没有 GPU 支持”

    我在这张专辑中上传了几张截图 https i stack imgur com TELST jpg https i stack imgur com TELST jpg 我正在尝试在 Visual Studio 2008 中的 OpenCV 中
  • 无法在 CUDA 中找到 1 到 100 数字的简单和?

    我正在研究使用 CUDA 的图像处理算法 在我的算法中 我想使用 CUDA 内核找到图像所有像素的总和 所以我在cuda中制作了内核方法 来测量16位灰度图像的所有像素的总和 但我得到了错误的答案 所以我在cuda中编写了一个简单的程序来查
  • 使用 Cuda 并行读取多个文本文件

    我想使用 CUDA 在多个文件中并行搜索给定字符串 我计划使用 pfac 库来搜索给定的字符串 问题是如何并行访问多个文件 示例 我们有一个包含 1000 个文件的文件夹 需要搜索 这里的问题是我应该如何访问给定文件夹中的多个文件 应该动态
  • 对 CUDA 操作进行计时

    我需要计算 CUDA 内核执行的时间 最佳实践指南说我们可以使用事件或标准计时函数 例如clock 在Windows中 我的问题是使用这两个函数给出了完全不同的结果 事实上 与实践中的实际速度相比 事件给出的结果似乎是巨大的 我实际上需要这
  • 布尔实现的atomicCAS

    我想弄清楚是否存在错误答案 https stackoverflow com a 57444538 11248508 现已删除 关于Cuda like的实现atomicCAS for bool是 答案中的代码 重新格式化 static inl
  • CUDA 代码会损坏 GPU 吗?

    在测试包含内存错误的 CUDA 时 我的屏幕被冻结了 重新启动后我无法再检测到显卡 我的代码是否有可能物理损坏该卡 这发生在 Ubuntu 14 04 下 我不知道该卡的型号 因为我无法检测到它 但我记得它是一张相当新的卡 感谢所有的评论我
  • CUDA 中的 JPEG 库

    我正在尝试在 CUDA 中压缩和解压缩图像 到目前为止我已经找到了这个库 http sourceforge net projects cuj2k source navbar http sourceforge net projects cuj
  • 为什么使用 boost::none 无法通过 nvcc 编译?

    我正在尝试编译以下代码 include
  • 了解流式多处理器 (SM) 和流式处理器 (SP)

    我正在尝试了解 GPU 的基本架构 我已经阅读了很多材料 包括这个非常好的答案 https stackoverflow com a 2213744 2386113 但我仍然很困惑 无法得到一个好的图片 我的理解 GPU 包含两个或多个流式多
  • 如何从尖点库矩阵格式获取原始指针

    我需要从尖点库矩阵格式获取原始指针 例如 cusp coo matrix
  • 将 cuda 数组传递给 Thrust::inclusive_scan

    我可以对 cpu 上的数组使用包容性扫描 但是否可以对 gpu 上的数组执行此操作 注释是我知道有效但我不需要的方式 或者 是否有其他简单的方法可以对设备内存中的数组执行包含扫描 Code include

随机推荐

  • 【目标检测】output with shape [1, 300, 300] doesn‘t match the broadcast shape [3, 300, 300]

    问题描述 训练SSD网络时报错 RuntimeError output with shape 1 300 300 doesn t match the broadcast shape 3 300 300 导致原因 数据集中存在单通道图片 解决
  • IT项目管理第四次作业

    一 你联合同学做一个年级微信公众号加强各班相互了解 联合活动 等 请编制项目章程和项目管理计划 指导该项目实施与运营 必须包含 WBS 和 甘特图 项目章程 项目名称 中山大学17级微信公众号 项目起止时间 2020年6月3日 2020年8
  • Spark大数据分析与实战笔记(第一章 Scala语言基础-2)

    文章目录 章节概要 1 2 Scala的基础语法 1 2 1 声明值和变量 1 2 2 数据类型 1 2 3 算术和操作符重载 1 2 4 控制结构语句 1 2 5 方法和函数 章节概要 Spark是专为大规模数据处理而设计的快速通用的计算
  • Mac 软件汉化教程(一)

    本篇教程旨在提供入门级汉化教程 意思就是最简单的 软件汉化也不是什么很神秘和高大上的事情 任何人都可以做汉化 主要工作就是找到软件需要汉化的英文字符串 再将其翻译成中文 当然 Mac 软件的汉化难易程度大不相同 大致可以分成三种 1 简单好
  • 解决OBS在Linux下无法录屏

    Linux下OBS无法录屏问题解决 因为OBS依赖Pipewire服务 所以就需要安装额外的依赖 sudo apt install pipewire pipewire pulse wireplumber
  • Pikachu (xss跨站脚本攻击)

    目录 xss概念 一 反射型 xss get 二 反射型 post 三 存储型 四 DOM型 五 xss盲注 六 xss之过滤 七 xss之htmlspecialchars 1 htmlspecialchars作用 flags 八 xss之
  • 基于openswan klips的IPsec实现分析(五)应用层和内核通信(2)

    基于openswan klips的IPsec实现分析 五 应用层和内核通信 内核操作 转载请注明出处 http blog csdn net rosetta 在数据发送一节讲过 加载模块时会执行pfkey init 初始化与用户层通信的PF
  • C++ stack容器详解

    C stack容器 stack容器的基本概念 stack的常用接口 1 构造函数 2 赋值操作 3 数据存取 4 大小操作 测试 stack容器的基本概念 stack是一种先进先出的数据结构 被称为栈 它只有一端可以出入 栈中进入数据称为
  • IO读写实例

    基本类型的读写 import java io public class TestDataStream public static void main String args throws IOException OutputStream o
  • SSE2的一些常用指令集介绍

    开门见山 前段时间学习OpenCV的FAST算法 中间有很多SSE2的指令集 深受其惑 下面我把学习过程中学到的一些指令集介绍给大家 希望能对大家有所帮助 m128i被称为128bits的整数 对其进行赋值时 可以调用 m128i mm s
  • MMKV原理详解

    性能对比 我们将 MMKV 和 SharedPreferences SQLite 进行对比 重复读写操作 1k 次 相关测试代码在Android MMKV mmkvdemo 结果如下图表 单进程性能 可见 MMKV 在写入性能上远远超越 S
  • 三、nginx两种压缩配置[gzip]

    一 nginx压缩 解释 通过配置参数 让nginx压缩指定后缀格式文件 然后发送给用户 但是这样这些压缩文件无法使用sendfile的高效传送 使用其能使得文件传输不经过程序 加载到缓存直接发送 相反off的话 需要在硬盘 缓存 程序 发
  • [Python人工智能] 十四.循环神经网络LSTM RNN回归案例之sin曲线预测

    从本专栏开始 作者正式开始研究Python深度学习 神经网络及人工智能相关知识 前一篇文章详细讲解了如何评价神经网络 绘制训练过程中的loss曲线 并结合图像分类案例讲解精确率 召回率和F值的计算过程 本篇文章将分享循环神经网络LSTM R
  • java文件的上传和下载_java文件上传和下载

    在web项目中上传文件夹现在已经成为了一个主流的需求 在OA 或者企业ERP系统中都有类似的需求 上传文件夹并且保留层级结构能够对用户行成很好的引导 用户使用起来也更方便 能够提供更高级的应用支撑 文件夹数据表结构 CREATETABLEI
  • 注解-宋红康

    目录 一 注解 Annotation 概述 二 常见的注解实例 三 如何自定义注解 四 JDK中的四个元注解 五 Java8注解的新特性 1 可重复注解 2 类型注解 一 注解 Annotation 概述 二 常见的注解实例 三 如何自定义
  • Android开发入门组件(十)——WebView

    今天主要写一下WebView 主要是在安卓应用的页面来加载或者写入网页 是比较常见的一种操作 加载网页 1 加载url 网络或者本地assets文件下的html文件 1 加载网络url webview loadUrl 相应的网址 直接在ac
  • 从外包辞职了,600小时后,我入职了字节跳动

    前言 没有绝对的天才 只有持续不断的付出 对于我们每一个平凡人来说 改变命运只能依靠努力 幸运 但如果你不够幸运 那就只能拉高努力的占比 2022年7月 我有幸成为了字节跳动的一名Java后端开发 相信同行都清楚 从外包进大厂有多难 运气之
  • c# --- 泛型解决输入和输出类型不确定问题

    一 背景 有这样一个需求 一个方法 他的返回值类型不确定 方法参数的类型不做要求 二 思考 返回值类型不确定 从继承的角度 所以类都是object的子类 返回object即可 但是这种方法是类型不安全的 需要进行类型转换 我们可以使用泛型解
  • HTML <small> 标签

    定义和用法
  • CUBLAS矩阵乘法

    include