CUDA 初体验

article/2025/10/7 23:34:44

  • CUDA Visual Profiler
  • CUDA编程指导
    • shared memory
    • Page locked out memory
  • C
    • CUDA 调用
    • CUDA 编程介绍
    • CUDA 数据同步

CUDA Visual Profiler

在上180645课程的时候,里面谈到使用CUDA来做矩阵乘法和k均值聚类的加速。在使用n卡的时候,有一个Visual Profiler的东西可以看到GPU的使用信息。

在安装好了CUDA以后,在Ubuntu上登录以后,使用X server。在Ubuntu命令行输入:

ssh -X < your_andrew_id>@ghcXX.ghc.andrew.cmu.edu

然后就登陆了远程服务器,接着呢使用:

computeprof &

如果遇到错误,退出登录再连接就好了。

这样就可以看到了GPU的使用信息了。然后如果是Windows的话,使用Xming或Cygwin。如果是OS X的话,使用XQuartz就可以了。

CUDA编程指导

使用CUDA编程,可以学习CUDA编程指南【1】。接下来我就大概过一遍编程指南。

threadIdx是三维的向量,可以表示为一维、二维、三维的线程索引。如果是二维的话,若尺寸是 (Dx,Dy) ,那么索引的就是 (x+yDx) 。如果是三维的,索引的就是(x,y,z),那么就是( x+yDx+zDxDy )

现在线程块一般是1024个,但是因为有多个线程块。所以总的线程数是每块线程数x线程块数。

这里写图片描述

通过调用__syncthreads()函数进行数据同步。

CUDA的每个线程、线程块等等的内存层次:
这里写图片描述

除了全局存储之外,还有两种额外的存储:常量和texture memory(这个玩样儿是啥?)。

CUDADeviceReset()的调用使得所有的配置初始化。

CUDA上的存储操作有cudaMalloc(), cudaFree(). cudaMemcpy()。

举一个例子:

// Device code
__global__ void VecAdd(float* A, float* B, float* C, int N)
{
int i = blockDim.x * blockIdx.x + threadIdx.x;
if (i < N)
C[i] = A[i] + B[i];
}
// Host code
int main()
{
int N = ...;
size_t size = N * sizeof(float);
// Allocate input vectors h_A and h_B in host memory
float* h_A = (float*)malloc(size);
float* h_B = (float*)malloc(size);
// Initialize input vectors
...
// Allocate vectors in device memory
float* d_A;
cudaMalloc(&d_A, size);
float* d_B;
cudaMalloc(&d_B, size);
float* d_C;
cudaMalloc(&d_C, size);
// Copy vectors from host memory to device memory
cudaMemcpy(d_A, h_A, size, cudaMemcpyHostToDevice);
cudaMemcpy(d_B, h_B, size, cudaMemcpyHostToDevice);
// Invoke kernel
int threadsPerBlock = 256;
int blocksPerGrid =
(N + threadsPerBlock - 1) / threadsPerBlock;
VecAdd<<<blocksPerGrid, threadsPerBlock>>>(d_A, d_B, d_C, N);
// Copy result from device memory to host memory
// h_C contains the result in host memory
cudaMemcpy(h_C, d_C, size, cudaMemcpyDeviceToHost);
// Free device memory
cudaFree(d_A);
cudaFree(d_B);
cudaFree(d_C);
// Free host memory
...
}

cudaMallocPitch(), cudaMalloc3D()可以用来分配内存。另外还有cudaMemcpy2D和cudaMemcpy3D来分配2D和3D的内存。P34行有例子。

shared memory

shared 标识,共享的内存比全局的内存更快。这里举了一个矩阵乘法的例子: P35

P41页有memory blocking存在,更加快。

Page locked out memory

和传统的malloc分配的内存相反的,这种比较固定。

cudaHostAlloc() 和 cudaFreeHost()。

在CUDA里面涉及数据同步和流的东西,这里有显示同步和隐式同步。还有更多数据流的东西,比如数据传过去kernel的时候有的已经在执行啦什么的。还有callback函数。

P57里面有各种API。

CUDA里面的硬件架构上,有SIMD和多线程。

C

一些CUDA的语法,涉及和C有关的东西。类似于API。

在这里,贴上矩阵的CUDA算法,最基本的,然后需要在上面进行加速:

#include <cuda.h>
#include <cuda_runtime.h>
#include "matrix_mul.h"
#define TILE_WIDTH 2namespace cuda
{__global__voidmatrix_mul_kernel(float *sq_matrix_1, float *sq_matrix_2, float *sq_matrix_result, int sq_dimension){int tx = threadIdx.x;int ty = threadIdx.y;float sum = 0.0f;for(int k = 0; k < sq_dimension; k++){sum += sq_matrix_1[ty*sq_dimension + k] * sq_matrix_2[k*sq_dimension + tx];}sq_matrix_result[ty*sq_dimension + tx] = sum;}voidmatrix_multiplication(float *sq_matrix_1, float *sq_matrix_2, float *sq_matrix_result, unsigned int sq_dimension){int size = sq_dimension * sq_dimension * sizeof(float);float *sq_matrix_1_d, *sq_matrix_2_d, *sq_matrix_result_d;/***************************************************1st Part: Allocation of memory on device memory  ****************************************************//* copy sq_matrix_1 and sq_matrix_2 to device memory */cudaMalloc((void**) &sq_matrix_1_d, size);cudaMemcpy(sq_matrix_1_d, sq_matrix_1, size, cudaMemcpyHostToDevice);cudaMalloc((void**) &sq_matrix_2_d, size);cudaMemcpy(sq_matrix_2_d, sq_matrix_2, size, cudaMemcpyHostToDevice);/*allocate sq_matrix_result on host */cudaMalloc((void**) &sq_matrix_result_d, size);/***************************************************2nd Part: Inovke kernel ****************************************************/dim3 dimBlock(sq_dimension, sq_dimension);dim3 dimGrid(1,1);matrix_mul_kernel<<<dimGrid, dimBlock, dimBlock.x * dimBlock.x * sizeof(float)>>>(sq_matrix_1_d, sq_matrix_2_d, sq_matrix_result_d, sq_dimension);/***************************************************3rd Part: Transfer result from device to host ****************************************************/cudaMemcpy(sq_matrix_result, sq_matrix_result_d, size, cudaMemcpyDeviceToHost);cudaFree(sq_matrix_1_d);cudaFree(sq_matrix_2_d);cudaFree(sq_matrix_result_d);}
} // namespace cuda

CUDA 调用

核函数是GPU每个thread上运行的程序。必须通过gloabl函数类型限定符定义。形式如下:

            __global__ void kernel(param list){  }

核函数只能在主机端调用,调用时必须申明执行参数。调用形式如下:

            Kernel<<<Dg,Db, Ns, S>>>(param list);

<<<>>>运算符内是核函数的执行参数,告诉编译器运行时如何启动核函数,用于说明内核函数中的线程数量,以及线程是如何组织的。

<<<>>>运算符对kernel函数完整的执行配置参数形式是<< < Dg, Db, Ns, S>>> 【2】

  • 参数Dg用于定义整个grid的维度和尺寸,即一个grid有多少个block。为dim3类型。Dim3 Dg(Dg.x, Dg.y, 1)表示grid中每行有Dg.x个block,每列有Dg.y个block,第三维恒为1(目前一个核函数只有一个grid)。整个grid中共有Dg.x*Dg.y个block,其中Dg.x和Dg.y最大值为65535。
  • 参数Db用于定义一个block的维度和尺寸,即一个block有多少个thread。为dim3类型。Dim3 Db(Db.x, Db.y, Db.z)表示整个block中每行有Db.x个thread,每列有Db.y个thread,高度为Db.z。Db.x和Db.y最大值为512,Db.z最大值为62。 一个block中共有Db.x*Db.y*Db.z个thread。计算能力为1.0,1.1的硬件该乘积的最大值为768,计算能力为1.2,1.3的硬件支持的最大值为1024。
  • 参数Ns是一个可选参数,用于设置每个block除了静态分配的shared Memory以外,最多能动态分配的shared memory大小,单位为byte。不需要动态分配时该值为0或省略不写。
  • 参数S是一个cudaStream_t类型的可选参数,初始值为零,表示该核函数处在哪个流之中。

CUDA 编程介绍

比如举个计算一个数字每个数字平方和的CUDA实现。

#include <stdio.h>   __global__ void square(float * d_out, float * d_in)
{  int idx = threadIdx.x;  float f = d_in[idx];  d_out[idx] = f * f;  
}  int main(int argc, char ** argv) 
{  const int ARRAY_SIZE = 64;  const int ARRAY_BYTES = ARRAY_SIZE * sizeof(float);  // generate the input array on the host   float h_in[ARRAY_SIZE];  for (int i = 0; i < ARRAY_SIZE; i++){  h_in[i] = float(i);  }  float h_out[ARRAY_SIZE];  // declare GPU memory pointers   float *d_in;  float *d_out;  // allocate GPU memory   cudaMalloc((void**) &d_in, ARRAY_BYTES);  cudaMalloc((void**) &d_out, ARRAY_BYTES);  // transfer the array to the GPU   cudaMemcpy(d_in, h_in, ARRAY_BYTES, cudaMemcpyHostToDevice);  // launch the kernel   square<<<1, ARRAY_SIZE>>>(d_out, d_in);  // copy back the result array to the CPU   cudaMemcpy(h_out, d_out, ARRAY_BYTES, cudaMemcpyDeviceToHost);  // print out the resulting array   for (int i =0; i < ARRAY_SIZE; i++) {  printf("%f", h_out[i]);  printf(((i % 4) != 3) ? "\t" : "\n");  }  cudaFree(d_in);  cudaFree(d_out);  return 0;  
}  

CUDA 数据同步

原本有问题的代码:

__global__ void shift(){  int idx = threadIdx.x;  __shared__ int array[128];  array[idx] = threadIdx.x;  if (idx < 127) {  array[idx] = array[idx + 1];  }  
}  

设置barrier:

__global__ void shift(){int idx = threadIdx.x;__shared__ int array[128];array[idx] = threadIdx.x;__syncthreads();//执行至此,数组中的每一个元素都被正确的赋值if (idx < 127) {int temp = array[idx + 1];__syncthreads();//将一行代码拆分成两行来设置一个barrier,这种技巧非常实用,执行至此,每一个线程都正确的取值array[idx] = temp;__syncthreads();//确保后续使用array的正确性}}

参考资料:
【1】CUDA 编程指南:http://docs.nvidia.com/cuda/pdf/CUDA_C_Programming_Guide.pdf
【2】CUDA 调用说明:http://blog.csdn.net/augusdi/article/details/12204121
【3】CUDA 核函数的参数解析:http://blog.csdn.net/a925907195/article/details/39500915


http://chatgpt.dhexx.cn/article/qLN8XUMm.shtml

相关文章

LogCluster算法

LogCluster - A Data Clustering and Pattern Mining Algorithm for Event Logs LogCluster - 事件日志的数据聚类和模式挖掘算法 Risto Vaarandi and Mauno Pihelgas TUT 数字取证和网络安全中心 塔林科技大学 爱沙尼亚塔林 0 概要 Abstract—Modern IT systems often pro…

机器学习,看这一篇就够了:回归算法,特征工程,分类算法,聚类算法,神经网络,深度学习入门

目录 前言 1机器学习概述 1.1机器学习简介 1.1.1机器学习背景 1.1.2机器学习简介 1.1.3机器学习简史 1.1.4机器学习主要流派 1.2机器学习、人工智能和数据挖掘 1.2.1什么是人工智能 1.2.2什么是数据挖掘 1.2.3机器学习、人工智能与数据挖掘的关系 1.3典型机器学习应…

Ubuntu18.04下Opencv的安装及使用实例

本文主要介绍了在Ubuntu18.04系统下练习编译、安装著名的C/C图像处理开源软件库Opencv 3.4.12&#xff08;过程多&#xff0c;耗时长&#xff0c;需要耐心和细心&#xff09; 目录 一、Opencv简介 二、Opencv安装 1.安装环境 2.下载Opencv3.4.12 3.解压安装包 4.使用cmak…

处理器架构分类

一 X86和X64 X86和X64分别代表Intel 32位和64位的处理器&#xff0c;这里有个前提是指Intel X86架构的处理器吧。而具体点应该是&#xff1a; 1. x86-32&#xff1a; 32位的X86处理器&#xff0c;平常会简写成x86 2. x86-64&#xff1a; 64位的X86处理器。平常会简写成x64 …

ARM 处理器架构简介

ARM 架构是构建每个 ARM 处理器的基础。ARM 架构随着时间的推移不断发展&#xff0c;其中包含的架构功能可满足不断增长的新功能、高性能需求以及新兴市场的需要。有关最新公布版本的信息&#xff0c;请参阅 ARMv8 架构。 ARM 架构支持跨跃多个性能点的实现&#xff0c;并已在许…

昇腾 (Ascend) AI 处理器:达芬奇架构

参考&#xff1a;《昇腾AI处理器架构与编程——深入理解CANN技术原理及应用》 目录 昇腾 AI 处理器背景主要的架构组成部件可扩展性 达芬奇架构 (DaVinci Architecture)计算单元矩阵计算单元CPU vs. GPU vs. Ascend改变矩阵的存储方式来提升矩阵计算的效率矩阵计算单元 (矩阵乘…

傻白入门芯片设计,指令集架构、微架构、处理器内核(十一)

早期计算机出现时&#xff0c;软件的编写都是直接面向硬件系统的&#xff0c;即使是同一计算机公司的不同计算机产品&#xff0c;它们的软件都是不能通用的,这个时代的软件和硬件紧密的耦合在一起&#xff0c;不可分离。 IBM为了让自己的一系列计算机能使用相同的软件,免去重复…

VS2012 处理器架构“x86”不匹配 通过配置管理器更改您的项目的目标处理器架构...

在VS2012中新建一个项目。然后引用之前VS2010写的一个基础类库。 VS2012编译通过但是出现警告。 所生成项目的处理器架构“MSIL”与引用“E:\work\C#\Dt.Utility\bin\Debug\Dt.Utility.exe”的处理器架构“x86”不匹配。这种不匹配可能会导致运行时失败。请考虑通过配置管理器更…

《嵌入式 - 嵌入式大杂烩》 处理器架构与指令集

大家天天都在使用手机,你知道你的手机使用的什么处理器?处理器又是何种架构呢?今天笔者就来谈谈处理器的架构和指令集。 我们知道一台手机最重要的就是处理器,也就是处理器,那么什么是处理器呢? 处理器就是一堆数字电路(架构)以高低电平的各种组合实现了各种基本的运…

『已解决』.NET报错:所生成项目的处理器框架“MSIL”与引用“wdapi_dotnet1021”的处理器架构“AMD64”不匹配

&#x1f4e3;读完这篇文章里你能收获到 处理器架构“AMD64”不匹配问题的处理方案&#xff0c;只需要鼠标点几下就解决这篇文章强烈建议收藏&#xff01;&#xff01;&#xff01;免得下次找不到 文章目录 一、现象二、解决方案 一、现象 .NET C#错误&#xff1a;所生成项目…

处理器架构——多发射处理器技术

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 多发射处理器总结数据冒险动态调度-Tomasulo算法GPU与CPU的多发射技术对比&#xff08;待考究&#xff09; 多发射处理器总结 无论是动态多发射还是静态多发射&…

认识多处理器架构

常见的多处理器架构有哪些&#xff1f; SMP(Symmetric Multi-Processor) 对称多处理器结构NUMA(Non-Uniform Memory Access) 非统一内存访问架构MPP(Massive Parallel Processing) 大规模并行处理结构 他们都是如何工作的&#xff1f; SMP 所谓对称多处理器结构&#xff0c…

.NET报错:所生成项目的处理器框架“MSIL”与引用“xxx”的处理器架构“AMD64”不匹配

一、现象 所生成项目的处理器架构“MSIL”与引用“System.Data.SQLite, Version1.0.60.0, Cultureneutral, PublicKeyTokendb937bc2d44ff139, processorArchitecturex86”的处理器架构“AMD64”不匹配。这种不匹配可能会导致运行时失败。请考虑通过配置管理器更改您的项目的目…

Linux 系统查询处理器架构

注意 给出的命令大多需要 root 权限才能运行&#xff0c;请确保您现在已经处于有 root 权限的环境下。 如果您现在没有切换到 root 账户下&#xff0c;那么请使用 su 或者 sudo -s 命令来进行切换。 确认处理器架构 执行下面的命令&#xff0c;根据输出结果查表&#xff1a…

自己编写自动同步脚本

Step1: 运行脚本&#xff0c;将结果保存到sync_date.log下; 执行的时候&#xff0c;将地址修改为slave ip --databases 指定为需要同步的db_name user 和password修改为对应的账号密码&#xff1b; /* #!/bin/bash #define sync function sync(){ apt-table-sync --execut…

Typora+Git+Gitee实现个人笔记自动同步

TyporaGitGitee配置markdown笔记自动同步 配置gitee 注册gitee账号 在你自己电脑上(这里以windows举例),生成公钥 打开你的公钥文件,复制全部内容 找到设置,添加公钥,将复制内容粘贴到指示位置,确定 创建一个仓库,找到你创建的仓库页面,复制ssh链接 配置Git软件 下载G…

FreeFileSync 同步自动备份RealTimeSync(自动同步工具)

&#xff0c;因此在文件大小相同时检测不同文件的唯一方法是阅读其内容。 &#xff08;1&#xff09;文件仅存在于一侧 ->仅在左侧 ->仅在右侧 &#xff08;2&#xff09;文件存在于双侧 ->相同文件 ->内容不同 3.3 按文件大小比较 如果文件大小相同&#xff…

如何实现文件的双向自动同步备份?

如果一份文件可以自动在你的2个存储硬盘里进行备份保存&#xff0c;你觉得如何呢?对于一个每天面对很多重要文件的上班族来说&#xff0c;每天要保存很多的资料文件。但是总是担心公司电脑的损坏&#xff0c;造成公司重要资料文件的全部丢失。 最开始没有接触到自动数据备份的…

批处理之FTP自动同步文件

1. FTP.exe工具 ftp.exe是Windows系统提供的一个FTP客户端命令行工具。通过ftp.exe可以完成登录&#xff0c;显示远程文件、下载、上传、重命名、删除远程文件等操作。 1.1. 命令参数 FTP [-v] [-d] [-i] [-n] [-g] [-s:filename] [-a] [-A] [-x:sendbuffer] [-r:recvbuffer]…

十二.deepin文件自动同步阿里云盘

timeshift作用强大&#xff0c;可以备份系统和恢复历史版本&#xff0c;但不够直观&#xff0c;主要是我也没用它恢复过&#xff0c;在deepin论坛看到有人制作了一款工具&#xff0c;可以按文件夹自动同步到阿里云盘&#xff0c;这对于及时把重要数据恢复到其他电脑太有用了。至…