CUDA 分块矩阵乘法

2023-11-06

cpp文件

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>       //为rand()及srand()提供函数声明
#include <time.h>       

extern "C" int mulWithCuda(float *c, const float *a, const float *b, int size);

int _tmain(int argc, _TCHAR* argv[])
{
    int i = 0, j = 0, k = 0;
    float sum = 0;
    int size = 8;
    srand(time(NULL));
    float * matrix_a = (float *)malloc(size * size * sizeof(float));     //创建一维数组
    float * matrix_b = (float *)malloc(size * size * sizeof(float));     //创建一维数组
    float * matrix_c = (float *)malloc(size * size * sizeof(float));     //创建一维数组
    float * matrix_d = (float *)malloc(size * size * sizeof(float));     //创建一维数组

    for (i = 0; i < size; i++)
    {
        for (j = 0; j < size; j++)
        {
            //生成随机数
            *(matrix_a + i * size + j) = (float)rand() / (RAND_MAX / 10);
            *(matrix_b + i * size + j) = (float)rand() / (RAND_MAX / 10);
        }
    }
    for (i = 0; i < size; i++)
    {
        for (j = 0; j < size; j++)
        {
            printf("%f ", *(matrix_a + i * size + j));
        }
        printf("\n");
    }
    printf("\n");

    for (i = 0; i < size; i++)
    {
        for (j = 0; j < size; j++)
        {
            printf("%f ", *(matrix_b + i * size + j));
        }
        printf("\n");
    }
    printf("\n");
    clock_t start = clock();
    for (i = 0; i < size; i++)
    {
        for (j = 0; j < size; j++)
        {
            sum = 0;
            for (k = 0; k < size; k++)
            {
                sum = sum + *(matrix_a + i * size + k) * (*(matrix_b + k * size + j));
            }
            *(matrix_d + i * size + j) = sum;
            printf("%f ", sum);
        }
        printf("\n");
    }
    clock_t end = clock();
    double interval = double(end - start) / CLK_TCK;
    printf("CPU运行时间为:%lf\n", interval);

 


    // Add vectors in parallel.
    clock_t start1 = clock();
    int cudaStatus = mulWithCuda(matrix_c, matrix_a, matrix_b, size);
    clock_t end1 = clock();
    double interval1 = double(end1 - start1) / CLK_TCK;
    printf("GPU运行时间为:%lf\n", interval1);
    //printf("加速比为:%lf\n", interval / interval1);
    for (i = 0; i < size; i++)
    {
    for (j = 0; j < size; j++)
    {
    //*(matrix_c + i * size + j) = *(matrix_a + i * size + j) + *(matrix_b + i * size + j);
    printf("%f ", *(matrix_c + i * size + j));
    }
    printf("\n");
    }
    // cudaDeviceReset must be called before exiting in order for profiling and
    // tracing tools such as Nsight and Visual Profiler to show complete traces.

    return 0;
}


kernel.cu


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

#include <stdio.h>
#define dimen 16

__global__ void mulKernel1(float* c, float* a, float* b, int size)
{
    float sum = 0;
    //创建共享存储器数组
    __shared__ float A[dimen][dimen];
    __shared__ float B[dimen][dimen];

    //计算线程的不同维度索引
    int bx=blockIdx.x;
    int by=blockIdx.y;
    int tx=threadIdx.x;
    int ty=threadIdx.y;
    //计算得到结果在线程块中的索引
    int row = by*dimen+ty;
    int col = bx*dimen+tx;

    
    for (int k=0;k<(size-1)/dimen+1;k++)
    {
        //加载数据到共享存储器
        if(k * dimen + tx < size && row < size)
        {
            A[ty][tx]=a[row*size+k*dimen+tx];
        }
        else
        {
            A[ty][tx] = 0;
        }
        if(k * dimen + ty< size && col < size)
        {
            B[ty][tx]=b[(k*dimen+ty)*size+col];
        }
        else
        {
            B[ty][tx] = 0;
        }    
        __syncthreads(); //同步块内其他线程,使A和B共享存储器中数据填满

        for(int m=0;m<dimen;m++)
            sum +=A[ty][m]*B[m][tx];
        __syncthreads(); //同步矩阵上移动的共享块,使得sum的值完整
    }
    //将sum值赋值到线程对应的矩阵位置
    if(row < size && col < size)
    {
        c[row*size+col]=sum;
    }

}
__global__ void mulKernel(float *c,float *a, float *b, int size)
{
    int threadx=threadIdx.x;
    int thready=threadIdx.y;
    int blockx=blockIdx.x;
    int blocky=blockIdx.y;
    int row = blockx*blockDim.x+threadx;
    int col = blocky*blockDim.x+thready;
    float sum=0;
    for(int i=0;i<size;i++)
        sum+=a[row*size+i]*b[i*size+col];
    if(row < size && col < size)            //增加判断条件,避免由于矩阵分块不匹配导致的计算错误
    {
        c[row*size+col]=sum;
    }
}

// Helper function for using CUDA to add vectors in parallel.
extern "C" int mulWithCuda(float *c, float *a, float *b, int size)
{
    float *dev_a = 0;
    float *dev_b = 0;
    float *dev_c = 0;
    cudaError_t cudaStatus;

    // Choose which GPU to run on, change this on a multi-GPU system.
    cudaStatus = cudaSetDevice(0);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaSetDevice failed!  Do you have a CUDA-capable GPU installed?");
        goto Error;
    }

    // Allocate GPU buffers for three vectors (two input, one output)    .
    cudaStatus = cudaMalloc((void**)&dev_c, size * size * sizeof(float));
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }

    cudaStatus = cudaMalloc((void**)&dev_a, size * size * sizeof(float));
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }

    cudaStatus = cudaMalloc((void**)&dev_b, size * size * sizeof(float));
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }

    // Copy input vectors from host memory to GPU buffers.
    cudaStatus = cudaMemcpy(dev_a, a, size * size * sizeof(float), cudaMemcpyHostToDevice);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

    cudaStatus = cudaMemcpy(dev_b, b, size * size * sizeof(float), cudaMemcpyHostToDevice);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

    dim3 grid((size-1)/dimen+1,(size-1)/dimen+1,1);
    dim3 block(dimen,dimen,1);

    // Launch a kernel on the GPU with one thread for each element.
    mulKernel1<<<grid, block>>>(dev_c, dev_a, dev_b, size);

    // Check for any errors launching the kernel
    cudaStatus = cudaGetLastError();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "addKernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
        goto Error;
    }
    
    // cudaDeviceSynchronize waits for the kernel to finish, and returns
    // any errors encountered during the launch.
    cudaStatus = cudaDeviceSynchronize();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching addKernel!\n", cudaStatus);
        goto Error;
    }

    // Copy output vector from GPU buffer to host memory.
    cudaStatus = cudaMemcpy(c, dev_c, size * size * sizeof(int), cudaMemcpyDeviceToHost);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

Error:
    cudaFree(dev_c);
    cudaFree(dev_a);
    cudaFree(dev_b);
    
    return cudaStatus;
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CUDA 分块矩阵乘法 的相关文章

  • TensorRT 多线程

    我正在尝试使用 python API 来使用 TensorRt 我试图在多个线程中使用它 其中 Cuda 上下文与所有线程一起使用 在单个线程中一切正常 我使用 docker 和 tensorrt 20 06 py3 图像 onnx 模型和
  • 有没有一种有效的方法来优化我的序列化代码?

    这个问题缺乏细节 因此 我决定创建另一个问题而不是编辑这个问题 新问题在这里 我可以并行化我的代码吗 还是不值得 https stackoverflow com questions 17937438 can i parallelize my
  • __device__ __constant__ 常量

    有什么区别吗 在 CUDA 程序中定义设备常量的最佳方法是什么 在 C 主机 设备程序中 如果我想将常量定义在设备常量内存中 我可以这样做 device constant float a 5 constant float a 5 问题 1
  • 如何为 CUDA 内核选择网格和块尺寸?

    这是一个关于如何确定CUDA网格 块和线程大小的问题 这是对已发布问题的附加问题here https stackoverflow com a 5643838 1292251 通过此链接 talonmies 的答案包含一个代码片段 见下文 我
  • 通过 cuFFT 进行逆 FFT 缩放

    每当我使用 cuFFT 绘制程序获得的值并将结果与 Matlab 的结果进行比较时 我都会得到相同形状的图形 并且最大值和最小值位于相同的点 然而 cuFFT 得到的值比 Matlab 得到的值大得多 Matlab代码是 fs 1000 s
  • cuda-gdb 错误消息

    我尝试使用 cuda gdb 调试我的 CUDA 应用程序 但遇到了一些奇怪的错误 我设置了选项 g G O0构建我的应用程序 我可以在没有 cuda gdb 的情况下运行我的程序 但没有得到正确的结果 因此我决定使用 cuda gdb 但
  • 大型跨平台软件项目的技巧/资源

    我将开始一个大型软件项目 涉及跨平台 GUI 和大量的数字运算 我计划用 C 和 CUDA 编写大部分应用程序后端 并用 Qt4 编写 GUI 我计划使用 Make 作为我的构建系统 这将是一个只有两名开发人员的项目 一旦我相对深入地了解它
  • CUDA:获取数组中的最大值及其索引

    我有几个块 每个块在整数数组的单独部分上执行 举个例子 块一从 array 0 到 array 9 块二从 array 10 到 array 20 我可以获得每个块的数组最大值的索引的最佳方法是什么 示例块一 a 0 到 a 10 具有以下
  • 云或烟雾的粒子系统

    我正在尝试使用 OpenGL 和 CUDA 制作一个简单的用于云和烟雾模拟的粒子系统 如何使粒子系统中的粒子表现得像真正的云或烟雾在低湍流风中的表现 我现在遇到的一些问题是 颗粒聚集成一个大球 粒子扩散到无限远 粒子突然弹射离开 我已经完成
  • CUDA NSight 未随 Windows 8 上的 CUDA 5.0 安装文件一起安装? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 据我所知 Nvidia 网站上没有 Nsight Eclipse 的下载链接 它说它将由 CUDA 5 安装本机安装 但并没有随CUDA安装一起安装
  • 为什么 cuCtxCreate 返回旧上下文?

    我已经安装了 CUDA SDK 4 2 64 CUDA工具包4 2 64 CUDA 驱动程序 4 2 64 我检查了 windows 中的每个 nvcuda dll 所有这些都是 4 2 版本 但是当我使用驱动程序 api 创建上下文并使用
  • 用于计算邻居列表的最佳 GPU 算法

    给定 3D 中数千个点的集合 我需要获取落在某个截止值 以欧几里得距离而言 内的每个粒子的邻居列表 并且如果可能的话 从最近到最远排序 在 CUDA 或 OpenCL 语言中 哪种 GPU 算法最快 我所知道的最快的 GPU MD 代码之一
  • 直接在主机上访问设备向量元素的最快方法

    我请您参考以下页面http code google com p thrust wiki QuickStartGuide Vectors http code google com p thrust wiki QuickStartGuide V
  • 完全禁用 NVCC 优化

    我正在尝试测量 GPU 上的峰值单精度触发器 为此我正在修改 PTX 文件以在寄存器上执行连续的 MAD 指令 不幸的是 编译器正在删除所有代码 因为它实际上没有做任何有用的事情 因为我没有执行任何数据的加载 存储 是否有编译器标志或编译指
  • cudaMalloc使用向量>进行管理 > C++ - NVIDIA CUDA

    我正在通过 NVIDIA GeForce GT 650M GPU 为我创建的模拟实现多线程 为了确保一切正常工作 我创建了一些辅助代码来测试一切是否正常 在某一时刻 我需要更新变量向量 它们都可以单独更新 这是它的要点 device int
  • 了解流式多处理器 (SM) 和流式处理器 (SP)

    我正在尝试了解 GPU 的基本架构 我已经阅读了很多材料 包括这个非常好的答案 https stackoverflow com a 2213744 2386113 但我仍然很困惑 无法得到一个好的图片 我的理解 GPU 包含两个或多个流式多
  • 为什么在 CUDA 中启动 32 倍数的线程?

    我参加了 CUDA 并行编程课程 并且看到了许多 CUDA 线程配置的示例 其中通常将所需的线程数四舍五入到最接近的 32 倍数 我知道线程被分组为 warp 并且如果您启动 1000 个线程 GPU 无论如何都会将其四舍五入到 1024
  • CUDA双指针内存复制[重复]

    这个问题在这里已经有答案了 我这样写了我的示例代码 int d ptr cudaMalloc void d ptr sizeof int N int tmp ptr N for int i 0 i
  • Simpson 的 Thrust 集成代码在两台使用 NVC++ 的机器上输出不同的结果

    我写了一个数值积分代码 include
  • CUDA 中的合作组

    自 CUDA 9 发布以来 显然可以将不同的线程和块分组到同一组中 以便您可以一起管理它们 这对我来说非常有用 因为我需要启动一个包含多个块的内核并等待所有块都同步 cudaThreadSynchronize 对我来说不值得 因为在线程同步

随机推荐

  • 解决IDEA无法安装插件的问题

    进入2018年以来 在IDEA插件中心中 安装插件经常安装失败 报连接超时的错误 如下 我们发现连接IDEA的插件中心使用的是https的链接 我们在浏览器中使用https访问插件中心并不能访问 而使用普通的http是可以访问插件中心的 因
  • 监控系统平台服务器,服务器监控平台系统

    服务器监控平台系统 内容精选 换一换 监控是保持云耀云服务器可靠性 可用性和性能的重要部分 通过监控 用户可以观察云耀云服务器资源 为使用户更好地掌握自己的云耀云服务器运行状态 公有云平台提供了云监控 您可以使用该服务监控您的云耀云服务器
  • 解决No module named 'pymysql'问题

    我使用的是Anaconda3 在项目中导入pymysql时报错 说明没有安装pymysql 安装就可以了 使用 conda install pymysql 正常情况应该是这样 这就安装成功了 如果你出现了这种情况
  • python向Excel读取一行数据

    pandas 1 0之前读取是用的ix 后来改为iloc或者loc 如下 import pandas as pd df pd read excel 1 xlsx sheet name student 可以通过sheet name来指定读取的
  • runtime.h-Functions-Working with Classes (二)

    文章目录 Working with Classes 二 class getIvarLayout class getWeakIvarLayout class addMethod class replaceMethod class addIva
  • JDK8安装及系统变量配置(包含错误处理)

    jdk安装 一 下载JDK 二 安装 三 配置系统变量 四 可能遇到的问题 1 显示已经安装的问题 或者 读取注册表项值失败 2 原因 3 解决 五 验证安装成功 一 下载JDK JDK下载官网 二 安装 双击之后 一直下一步就ok 三 配
  • 【JAVA+oracle】数据库综合型实验----教务管理系统

    前言 这次实验用到了很久没写的javaswing 其中各种组件的使用可谓是花了一番工夫复习 其中遇到最大的问题是如何将java和oracle进行连接 这个问题搞了我一个晚上 一开始用的是eclipse 代码是没问题的 死活连不上 第二天把代
  • springboot当中配置mybatis分页插件

    这篇文章主要介绍了spring boot集成pagehelper 记录使用pagehelper的两种配置方式 目录 一 直接使用pagehelper 1 导入依赖 2 配置pagehelper 3 代码写法 二 使用pagehelper s
  • GPT2训练自己的对话问答机器人

    GPT2训练自己的对话问答机器人 1 环境搭建 2 理论研究 3 模型训练与测试 3 1语料tokenize 3 2用GPT2训练数据 3 3人机交互 4 效果展示 1 环境搭建 这里我搭建了虚拟的3 6环境 conda create n
  • 学会搭建小程序生鲜商城,开启生鲜电商新模式

    电商平台的出现 为人们带来了极大的便利 然而 传统的电商平台已经不能满足消费者对于购物体验的要求 如今 小程序生鲜商城因其轻量化 高效率等特点 成为了众多卖家的首选 本文将介绍如何学会搭建小程序生鲜商城 并以一个实际案例作为例子 解析运用技
  • python控制台输入、输出

    python控制台输入 输出 上一篇文章 python 注释 变量 类型 下一篇文章 Python运算符 比较 逻辑运算符 1 输出 简单输出 print 我是简单的字符串输出 控制台运行结果 我是简单的字符串输出 格式化输出 age 18
  • jenkins shell脚本执行权限不够解决办法

    自己服务器搭建jenkins执行操作的时候 没有相应的权限 解决这个问题的时候 做了一些笔记分享给大家 1 查看jenkins默认用户 vi etc sysconfig jenkins 复制代码 找到JENKINS USER发现默认用户je
  • JDBC入门

    JDBC基础部分 问题一 JDBC是什么 为什么会存在JDBC 作用是什么 JDBC Java DataBase Connection 是用于跟数据库进行交互的 由JDK统一提供 可以为多种关系型数据库提供统一的标准 但是是各大厂商进行实例
  • 亚信科技AntDB数据库携“U8C+AntDB联合产品”亮相“2023全球商业创新大会”,开启生态合作新篇章

    8月18 19日 近万人齐聚上海国家会展中心 带着对数字化 数智化趋势和热点的关注 以满腹热情投身到以 数据驱动 智能运营 为主题的 2023全球商业创新大会 共商新技术条件下企业信息化出现的新课题 新挑战 共享数智化升级创新成果 亚信科技
  • 【Python】TXT文本文件转换成JSON格式

    主要分为两个部分 1 txtToJson 函数读取指定路径下的所有文件 转换成如下格式 name1 content1 name2 content2 2 saveInJsonFile 函数将处理好的json格式数据和保存的文件路径作为函数参数
  • Android数据加密之MD5加密

    一 前言 项目中无论是密码的存储或者说判断文件是否是同一文件 都会用到MD5算法 今天来总结一下MD5加密算法 二 什么是MD5加密 MD5英文全称 Message Digest Algorithm 5 翻译过来是 消息摘要算法5 由MD2
  • c语言结构体变量所占字节计算,【C语言】结构体占用字节数及存储与空间分配...

    我们都知道在数据类型中 char类型占1个字节 short占2个字节 int占4个字节 long占8个字节等等 在计算结构体大小时需要考虑其内存布局 结构体在内存中存放是按单元存放的 每个单元多大取决于结构体中最大基本类型的大小 下面我们看
  • 网络工程师常用的命令整理-windows版,还不快收藏起来

    一 ping命令 1 ping ping是最常用的实用程序之一 用来确定网络的连通性 ping是个使用频率极高的实用程序 主要用于确定网络的连通性pi 如果ping通一个地址 那么基本可以排除物理层数据链路层的故障等 ping 的命令格式通
  • 使用联机搜索求解Wumpus World

    使用 JavaScript 重写的算法网页 https yuqingxiong github io Wumpus World Problem github仓库地址 https github com YuqingXiong Wumpus Wo
  • CUDA 分块矩阵乘法

    cpp文件 include stdafx h include