使用 NVProf 检测 CUDA kernel 的 bank conflict

news2024/11/14 23:11:16

使用 NVProf 检测 CUDA kernel 的 bank conflict

NVProf 指令

使用 NVProf 可以对 bank conflict 进行检测:

nvprof --events shared_ld_bank_conflict,shared_st_bank_conflict <app> [args...]

其中:

  • --events 选项指定的 shared_ld_bank_conflict,shared_st_bank_conflict分别代指从 shared memory 加载(读取)时产生的 bank conflict, 以及向 shared memory 存储(写入)时产生的 bank conflict.
  • <app> [args...] 即要检测的 CUDA 二进制程序及其参数.

额外说明

值得一提的是, 如果没有从 shared memory 读取的指令, 且没有使用 -G 编译, 则两种 bank conflict 事件都无法检测出来, 即使存在向 shared memory 写入产生的 bank conflict.
(没有读取的 bank conflict 很好理解, 因为都没有从 shared memory 读取数据; 而至于写入的 bank conflict, 应该是编译器做了一定的优化, 即 shared memory 虽被写入但数据没有被读取, 则写入是没有意义的, 这部分代码实际并不执行, 所有写入的 bank conflict 就不会检测到了.)

这个主要作用是, 当我们对自己写的 kernel 的 bank conflict 进行检测的时候, 要确保保留对 shared memory 读取的相关代码或设置 -G 编译选项, 否则可能会影响 bank conflict 的检测.

举例

以下代码是一个很简单的 CUDA kernel 示例, 考虑到 bank conflict 是 warp 层面的问题, 所有 kernel 中我定义了 warp_id, land_id 等变量便于后续 bank conflict 的说明.

#include <iostream>
#include <cstdio>
#include <vector>
#include <cuda.h>

using namespace std;

constexpr int SIZE_A = 64;
constexpr int SIZE_C = 64;

__global__ void kernel(const int* a, int* c) {
    auto tid = (blockIdx.x * blockDim.x + threadIdx.x);
    auto lane_id = threadIdx.x & 0x1F;
    auto warp_id = tid >> 5;
    auto warp_in_block = threadIdx.x >> 5;

    __shared__ int shm[SIZE_A];

    if (tid < SIZE_A) {
        shm[warp_id * 32 + lane_id] = a[warp_id * 32 + lane_id];
    }
    
    if (tid < SIZE_C) {
        c[warp_id * 32 + lane_id] = shm[warp_id * 32 + lane_id];
    }
}

int main() {
    vector<int> a(SIZE_A);

    for (int i = 0; i < SIZE_A; ++i) {
        a[i] = i;
    }

    int* d_a;
    cudaMalloc(&d_a, sizeof(int) * SIZE_A);
    cudaMemcpy(d_a, a.data(), sizeof(int) * SIZE_A, cudaMemcpyHostToDevice);

    int* d_c;
    cudaMalloc(&d_c, sizeof(int) * SIZE_C);
    cudaMemset(d_c, 0, sizeof(int) * SIZE_C);

    kernel<<<1, 128>>>(d_a, d_c);

    vector<int> c(SIZE_C);
    cudaMemcpy(c.data(), d_c, sizeof(int) * SIZE_C, cudaMemcpyDeviceToHost);

    for (auto x : c) {
        cout << x << " ";
    }
    cout << endl;

    cudaFree(d_c);
    cudaFree(d_a);

    return 0;
}

kernel() 函数完成的功能很简单, 就是想数组 a 中的一部分数据先写至 shared memory shm, 再写入到 c 中. 在没有额外说明时, 不使用 -G 选项编译代码.
很明显的是, 由于 shm 的读写时, 每个 warp 的 32 个线程分片读取不同的 4 字节数据, 因此代码没有 bank conflict.
在这里插入图片描述
使用上述 NVProf 指令检测, 结果也印证了上述推断.

现在将 Kernel 修改如下:

__global__ void kernel(const int* a, int* c) {
    auto tid = (blockIdx.x * blockDim.x + threadIdx.x);
    auto lane_id = threadIdx.x & 0x1F;
    auto warp_id = tid >> 5;
    auto warp_in_block = threadIdx.x >> 5;

    __shared__ int shm[SIZE_A];

    // if (tid < SIZE_A) {
    //     shm[warp_id * 32 + lane_id] = a[warp_id * 32 + lane_id];
    // }
    for (auto i = threadIdx.x; i < SIZE_A; i += blockDim.x) {
        shm[(i % 2) * SIZE_A / 2 + i / 2] = a[i];
    }

    if (tid < SIZE_C) {
        c[warp_id * 32 + lane_id] = shm[warp_id * 32 + lane_id];;
    }
}

我们在读取 a 数组到 shared memory 的时候, 进行了一点修改. 可以看到, 对应相邻的两个线程, tt+1 (假设 t % 2 ==0), 则一个写入到 shm[t/2], 一个写入到 shm[SIZE_A/2+(t+1)/2]shm[32+t/2], 由于恰好差了 32 个元素, 因此会访问到相同的 bank, 会触发 bank conflict. 通过 NVProf 检测也得到了证实:
在这里插入图片描述
这里的 2 次, 原因笔者猜测为 SIZE_A 大小为 64, 对应 2 个 warp, 每个 warp 相邻的奇数线程和偶数线程访问同一 bank, 以 warp 为单位, 每个 warp 产生 1 个 bank conflict, 共 2 个.

但如果我们将后面将 shm 写入 c 数组的代码注释掉, 即没有从 shared memory 读取的代码, 则可以看到 NVProf 并不会检测到刚刚的 shared_st_bank_conflict.

    if (tid < SIZE_C) {
        c[warp_id * 32 + lane_id] = shm[warp_id * 32 + lane_id];;
    }

在这里插入图片描述

但如果我们在编译的时候使用 -G 选项, 则可以看到刚刚的 shared_st_bank_conflict 有可以被检测到了:
在这里插入图片描述

因此, 可以推断出, 在默认情况下, 编译器对于不读取的 shared memory 的写入操作会进行优化, 实际上并不会执行 shared memory 的写入操作, 而 debug 模式 (带 -G 选项)时, 则不会进行该优化.

如下代码展示了在从 shared memory shm 读取到 c 数组时的 bank conflict.

constexpr int SIZE_A = 64;
constexpr int SIZE_C = 32;

__global__ void kernel(const int* a, int* c) {
    auto tid = (blockIdx.x * blockDim.x + threadIdx.x);
    auto lane_id = threadIdx.x & 0x1F;
    auto warp_id = tid >> 5;
    auto warp_in_block = threadIdx.x >> 5;

    __shared__ int shm[SIZE_A];

    if (tid < SIZE_A) {
        shm[warp_id * 32 + lane_id] = a[warp_id * 32 + lane_id];
    }

    if (tid < SIZE_C) {
        // c[warp_id * 32 + lane_id] = shm[warp_id * 32 + lane_id];
        c[warp_id * 32 + lane_id] =
            shm[warp_in_block * 32 + lane_id / 8 + (lane_id % 2) * 32];
    }
}

可以看到, 相邻的 8 个线程分奇偶访问同一 bank 的两个地址. NVProf 输出如下:
在这里插入图片描述

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

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

相关文章

【Django使用】10大章31模块md文档,第5篇:Django模板和数据库使用

当你考虑开发现代化、高效且可扩展的网站和Web应用时&#xff0c;Django是一个强大的选择。Django是一个流行的开源Python Web框架&#xff0c;它提供了一个坚实的基础&#xff0c;帮助开发者快速构建功能丰富且高度定制的Web应用 全套Django笔记直接地址&#xff1a; 请移步这…

camera-caps:Jetson设备上的一种实用的V4L2可视化界面

camera-caps&#xff1a;Jetson设备上的一种实用的V4L2可视化界面 github地址是&#xff1a; https://github.com/jetsonhacks/camera-caps 注意&#xff1a;Jetpack5.x需要选择tag 5.x版本

【基础知识】AB软件RSLinx的版本说明

哈喽&#xff0c;大家好&#xff0c;我是雷工&#xff01; 之前对AB的软件了解比较少&#xff0c;在工作中未接触过&#xff0c;最近一次现场勘察时&#xff0c;有很多中控系统都是AB的&#xff0c;借此机会对AB软件有了些许了解。 一、RSLinx是什么软件&#xff1f; RSLinx是…

【LeetCode刷题-回溯】-- 46.全排列

46.全排列 方法&#xff1a;回溯法 一种通过探索所有可能的候选解来找出所有的解的算法&#xff0c;如果候选解被确认不是一个解&#xff0c;回溯法会通过在上一步进行一些变化抛弃该解&#xff0c;即回溯并且再次尝试 使用一个标记数组表示已经填过的数 class Solution {pu…

vue3自定义拖拽指令

<template><div v-move class"box"></div> </template><script setup lang"ts"> import { Directive } from vue const vMove:Directive (el:HTMLElement) >{const mousedown (e:MouseEvent) >{// 鼠标按下const s…

『 C++类与对象 』多态之单继承与多继承的虚函数表

文章目录 &#x1fae7; 前言&#x1fae7; 查看虚表&#x1fae7; 单继承下的虚函数表&#x1fae7; 多继承下的虚函数表 &#x1fae7; 前言 多态是一种基于继承关系的语法,既然涉及到继承,而继承的方式有多种: 单继承多继承棱形继承棱形虚拟继承 不同的继承方式其虚表的形…

redis运维(十八)pipeline

一 pipeline 流水线 说明&#xff1a; 这里讲解的不是jenkins的pipeline流水线这里pipeline: 管道 redis为什么要提供pipeline功能 事务和pipeline ① pipeline的理念 强调&#xff1a;单纯的pipeline跟事务没有关系redis-cli --pipe --> 使用了pipeline机制说明&a…

【Skynet 入门实战练习】游戏模块划分 | 基础功能模块 | timer 定时器模块 | logger 日志服务模块

文章目录 游戏模块基础功能模块定时器模块日志模块通用模块 游戏模块 游戏从逻辑方面可以分为下面几个模块&#xff1a; 注册和登录网络协议数据库玩法逻辑其他通用模块 除了逻辑划分&#xff0c;还有几个重要的工具类模块&#xff1a; Excel 配置导表工具GM 指令测试机器人…

CAD图纸设计在线协同、CAD图纸设计在线协同方案?

CAD图纸设计在线协同、CAD图纸设计在线协同方案&#xff1f; CAD图纸设计在线协同&#xff0c;在企业产品研发效能的提升中发挥着重要作用&#xff0c;技术应用的深入发展为不同场景的协作带来了全新的应用模式&#xff0c;工业设计领域亦是如此。 在CAD图纸设计与管理过程中&a…

RabbitMQ 搭建和工作模式

MQ基本概念 1. MQ概述 MQ全称 Message Queue&#xff08;[kjuː]&#xff09;&#xff08;消息队列&#xff09;&#xff0c;是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信。 &#xff08;队列是一种容器&#xff0c;用于存放数据的都是容器&#xff0…

【分布式】小白看Ring算法 - 03

相关系列 【分布式】NCCL部署与测试 - 01 【分布式】入门级NCCL多机并行实践 - 02 【分布式】小白看Ring算法 - 03 【分布式】大模型分布式训练入门与实践 - 04 概述 NCCL&#xff08;NVIDIA Collective Communications Library&#xff09;是由NVIDIA开发的一种用于多GPU间…

SQL进阶学习

1.[NISACTF 2022]join-us sql报错注入和联合注入 过滤&#xff1a; as IF rand() LEFT by updatesubstring handler union floor benchmark COLUMN UPDATE & sys.schema_auto_increment_columns && 11 database case AND right CAST FLOOR left updatexml DATABA…

CLion安装与配置教程

目录 一、下载并安装CLion1、下载1、官网&#xff1a;2、注意&#xff1a; 2、安装1、下载完成后&#xff0c;直接点击安装包安装&#xff0c;即可。2、开始安装&#xff0c;然后下一步3、可以在此处自定义地址&#xff0c;然后下一步4、根据系统版本选择&#xff0c;然后下一步…

Linux:虚拟机安装Ubuntu系统

一、下载Ubuntu 地址&#xff1a;https://cn.ubuntu.com/download/desktop 二、安装 以上配置完成后&#xff0c;点击完成按钮&#xff0c;接下来就是一段较长时间的等待安装过程。 安装完成后&#xff0c;还有一些系统性配置。 系统配置非常简单&#xff0c;全部next即可。…

开源 GPU池化软件 | (AI人工智能训练平台、AI人工智能推理平台)

GPU池化软件 | (AI人工智能训练平台、AI人工智能推理平台) 讨论群v:&#x1f680;18601938676 一、AI人工智能开发-------------面临的问题和挑战 1. GPU管理难题 1.1 资源管理难&#xff1a;算力资源昂贵&#xff0c;但是缺乏有效管理&#xff0c;闲置情况严重。 1.2 用户…

【uniapp】uniapp开发小程序定制uni-collapse(折叠面板)

需求 最近在做小程序&#xff0c;有一个类似折叠面板的ui控件&#xff0c;效果大概是这样 代码 因为项目使用的是uniapp&#xff0c;所以打算去找uniapp的扩展组件&#xff0c;果然给我找到了这个叫uni-collapse的组件&#xff08;链接&#xff1a;uni-collapse&#xff09…

Django 入门学习总结4

视图是Django应用程序在Python语言中提供特定的方法并对应于有特定的模板的网页。网页的页面通过视图的方式进行跳转。 在投票系统中&#xff0c;有四个视图&#xff1a; 首页视图&#xff0c;显示最新的问题列表。细节视图&#xff0c;显示问题文本&#xff0c;通过表单可以…

【标注数据】labelme的安装与使用

这里写目录标题 下载标数据 下载 标数据 打开自动保存 创建矩形

FreeRTOS的并行与并发思考

FreeRTOS的任务触发是由滴答时钟触发SysTick中断来触发调度器执行或阻塞或挂起和切换任务的。 首先是任务的并发能力&#xff0c;FreeRTOS的任务执行是基于全抢占调度机制&#xff0c;任务优先级按在就绪列表中由高到低排布&#xff0c;系统首先执行最高优先级任务&#xff0c;…

【element优化经验】怎么让element-ui中表单多语言切换排版不乱

目录 前言&#xff1a; 痛点&#xff1a; 1.左对齐&#xff0c;右对齐在中文和外语情况下字数不同&#xff0c;固定宽度会使名称换行&#xff0c;不在整行对齐&#xff0c;影响美观。 2.如果名称和输入框不在一行&#xff0c;会使页面越来越长 3.label-width值给变量&#…