1、CUDA 编程基础

系列文章目录

第1章 CUDA 编程基础

文章目录

前言

回顾计算机技术的发展,特别是摩尔定律的影响,计算能力的快速提升。然而,随着晶体管尺寸的缩小和频率的停滞,单线程性能增长放缓。为了继续提升性能,多核处理器开始普及,促使软件开发者开始考虑并行计算。

CPU和GPU分别代表了这两种设计方法。GPU是吞吐量导向的,拥有众多弱小的ALU,通过流水线处理提高算术吞吐量。GPU的成功在于其高并行性和高吞吐量,以及能够分摊高昂的固定成本的大量销售额。

随着CUDA的普及,GPU计算的应用领域迅速扩大,尤其是在机器学习领域。如今,GPU已经成为全球顶级超级计算机的重要组成部分,并且在能源效率方面表现出色。课程将关注如何以通用的方式编程GPU,以及如何利用GPU加速科学计算和深度学习工作负载。

1、nvidia-smi指令

  • 查询GPU 详细信息 nvidia-smi -q
  • 查询特定GPU 详细信息 nvidia-smi -h
  • 显示GPU 特定信息 nvidia-smi --q --i 0 --d MEMORY

2、nvcc

编译CUDA 文件指令:nvcc hello.cu -o hello

3、核函数(Kernel function)

1、核函数在GPU 上进行并行 执行

2、注意:

(1)限定词__global__ 修饰

(2)返回值必须是void

3、形式:

c 复制代码
__global__ void kernel_function(argument arg)
{
	printf("Hello World from the GPU!\n");
}


void __global__ kernel_function(argument arg)
{
	printf("Hello World from the GPU!\n");
}

kernel的限制:

  • 仅能获取device memory 。
  • 必须返回void类型。
  • 不支持可变数目参数。
  • 不支持静态变量。
  • 不支持函数指针。
  • 核函数具有异步性

4、GPU 和 CPU的区别

5、GPU计算能力

1、每款GPU 都有用于标识"计算能力"(compute capability )

的版本号

2、形式X.Y Y,X 标识主版本号,Y 表示次版本号

并非GPU 的计算能力越高,性能就越高

6、设备信息查询和设置

1、运行时API查询GPU信息

c 复制代码
/*********************************************************************************************
 * file name  : query.cu
 * brief      : 运行时API查询GPU信息
***********************************************************************************************/

#include "../tools/common.cuh"
#include <stdio.h>

int main(void)
{
    int device_id = 0;
    ErrorCheck(cudaSetDevice(device_id), __FILE__, __LINE__);

    cudaDeviceProp prop;
    ErrorCheck(**cudaGetDeviceProperties(&prop, device_id)**, __FILE__, __LINE__);

    printf("Device id:                                 %d\n",
        device_id);
    printf("Device name:                               %s\n",
        prop.name);
    printf("Compute capability:                        %d.%d\n",
        prop.major, prop.minor);
    printf("Amount of global memory:                   %g GB\n",
        prop.totalGlobalMem / (1024.0 * 1024 * 1024));
    printf("Amount of constant memory:                 %g KB\n",
        prop.totalConstMem  / 1024.0);
    printf("Maximum grid size:                         %d %d %d\n",
        prop.maxGridSize[0], 
        prop.maxGridSize[1], prop.maxGridSize[2]);
    printf("Maximum block size:                        %d %d %d\n",
        prop.maxThreadsDim[0], prop.maxThreadsDim[1], 
        prop.maxThreadsDim[2]);
    printf("Number of SMs:                             %d\n",
        prop.multiProcessorCount);
    printf("Maximum amount of shared memory per block: %g KB\n",
        prop.sharedMemPerBlock / 1024.0);
    printf("Maximum amount of shared memory per SM:    %g KB\n",
        prop.sharedMemPerMultiprocessor / 1024.0);
    printf("Maximum number of registers per block:     %d K\n",
        prop.regsPerBlock / 1024);
    printf("Maximum number of registers per SM:        %d K\n",
        prop.regsPerMultiprocessor / 1024);
    printf("Maximum number of threads per block:       %d\n",
        prop.maxThreadsPerBlock);
    printf("Maximum number of threads per SM:          %d\n",
        prop.maxThreadsPerMultiProcessor);

    return 0;
}

2、设置GPU 设备

1、获取GPU设备数量

c 复制代码
int iDeviceCount = 0;
cudaGetDeviceCount(&iDeviceCount);

2、设置GPU执行时使用的设备

c 复制代码
int iDev = 0;
cudaSetDevice(iDev)

完整实例:

c 复制代码
#pragma once
#include <stdlib.h>
#include <stdio.h>

cudaError_t ErrorCheck(cudaError_t error_code, const char* filename, int lineNumber)
{
    if (error_code != cudaSuccess)
    {
        printf("CUDA error:\r\ncode=%d, name=%s, description=%s\r\nfile=%s, line%d\r\n",
                error_code, cudaGetErrorName(error_code), cudaGetErrorString(error_code), filename, lineNumber);
        return error_code;
    }
    return error_code;
}

void setGPU()
{
    // 检测计算机GPU数量
    int iDeviceCount = 0;
    cudaError_t error = ErrorCheck(cudaGetDeviceCount(&iDeviceCount), __FILE__, __LINE__);

    if (error != cudaSuccess || iDeviceCount == 0)
    {
        printf("No CUDA campatable GPU found!\n");
        exit(-1);
    }
    else
    {
        printf("The count of GPUs is %d.\n", iDeviceCount);
    }
    // 设置执行
    int iDev = 0;
    error = ErrorCheck(cudaSetDevice(iDev), __FILE__, __LINE__);
    if (error != cudaSuccess)
    {
        printf("fail to set GPU 0 for computing.\n");
        exit(-1);
    }
    else
    {
        printf("set GPU 0 for computing.\n");
    }
}
相关推荐
木木学AI7 分钟前
AI客服系统技术选型:Agentic架构与传统规则引擎的能力差异评估
人工智能·架构
hhzz9 分钟前
Python大数据实战(十六):音乐推荐系统——基于协同过滤算法构建个性化歌单引擎
大数据·人工智能·python·数据挖掘·数据分析
带娃的IT创业者21 分钟前
突破算力与安全的边界:深度解析 Mythos AI 的“受信发布”机制与技术影响
人工智能·安全·大语言模型·ai安全·mythos ai·受信发布·ai监管
dreamread21 分钟前
2026紫微八字同排工具怎么选:看盘面切换、功能边界和学习路径
人工智能·软件工具·传统文化
耍酷的魔镜27 分钟前
核心设计理念:5W2H、JSON-LD 与通用知识图谱
人工智能·json·知识图谱
星河耀银海1 小时前
大模型安全:对抗攻击与防御方法
人工智能·安全·大模型
xsdick1 小时前
抛弃 OpenClawd吧!我用 Go 打造了企业级 Swarm(蜂群)agent,更智能,更安全、性能快 5 倍、成本直降80%
人工智能·ai·ai编程
冬奇Lab2 小时前
Workflow 系列(10):企业级架构——注册表、组合与治理
人工智能·工作流引擎
冬奇Lab2 小时前
每日一个开源项目(第153篇):AgentsView - 跨 30+ AI 编程工具的会话分析和费用追踪,本地优先,无需账号
人工智能·开源·ai编程
泛普软件2 小时前
工程合约管理软件具备哪些核心功能,解决合同结算各类纠纷难题
大数据·人工智能·区块链