cuda编程学习笔记 第二章 cuda memory management

2023-11-10

应用的性能可能有 75% 都花费在内存相关问题上。

NVPROF and NVVP

这俩是调试工具,不知道是不是基于CUPTI (CUDA Profiler Tools Interface)。

NVPROF是命令行工具,nvvp是可视化工具。

nvvp有四个模块:Timeline,Summary,Guide,Analysis results
其中 Guide 适合新手,新手应该多注意。

为了分析出应用的性能瓶颈,我们需要timeling analysis 和 metric analysis

编译:
要include cuda_profiler_api.h 和 helper_functions.h
命令1
nvcc -I"D:/cuda/NVIDIA Corporation_v10.1/common/inc" -gencode arch=compute_61,code=sm_61 -Xcompiler /wd4819 -o sgemm sgemm.cu
命令2 创建 nvvp文件
nvprof -o sgemm.nvvp .\sgemm.exe
13388 NVPROF is profiling process 13388, command: .\sgemm.exe
Operation Time= 0.0046 msec
13388 Generated result file: D:\codes\Learn-CUDA-Programming-master\Learn-CUDA-Programming-master\Chapter02\02_memory_overview\01_sgemm\sgemm.nvvp

运行nvvp,打开 sgemm.nvvp文件

Global memory / device memory

global memory 是从host复制过去的默认空间
cudaMalloc 和 cudaFree cudaMemcpy

coalesced memory access / uncoalesced memory access

warp:32threads running in SMs。
例如 一个SM运行两个block,每个block128线程,则一共 8 个 warp。这些 warp 公用一个SM的shared memory。
每个warp中的线程以SIMT模式运行,也就是所有线程同时运行同一个命令

warp下的内存访问需要coalesced memory access,squential memory access is adjacent.

总而言之尽量连续访问、数据aligned

texture memory

一般用来存储大部分线程都要访问的少量数据,比如参数之类。同一个warp的线程访问同一个地址会导致所有线程在每个时钟周期请求数据,但是在texture memory上有优化。2D访问、3D访问也有优化,总之就是读的快、不能写。

shared memory

shared memory以banks的形式排列,要防止同一个warp里的线程同时访问同一个bank,至于不同warp之间的不太清楚。

registers

local variables are stored in registers
尽量别弄太多本地变量,寄存器和thread有关

pinned memory

尽量不在host 和 device之间传输数据
用pinned memory
把许多小数据传输合并成一个大batch
用计算来掩盖传输

传输数据时默认先创建一个pinned memory,然后将一个个page复制过去,再从pinned memory里将数据复制到device(通过DMA)。通过cudaMallocHost可以之间分配一个pinned memory。

Unified memory

给GPU和CPU提供一个统一的地址
cudaMallocManaged分配空间,不是立刻分配,下一次host第一个访问该空间就分配host,否则device。(first touch)

当device需要访问某个page,但是page正在host映射的空间里,这时会让host取消映射,transfer这个page到device的物理空间,device再映射这个page。

warp per page 技术,每个warp负责64K,一个page:

__global__ void init(int n, float *x, float *y) {
    int lane_id = threadIdx.x & 31;//本线程是该warp的第几个线程
    size_t warp_id = (threadIdx.x + blockIdx.x * blockDim.x) >> 5;//blockDim.x是一个block的线程数
    size_t warps_per_grid = (blockDim.x * gridDim.x) >> 5;//
    size_t warp_total = ((sizeof(float)*n) + STRIDE_64K-1) / STRIDE_64K;//pages

    // if(blockIdx.x==0 && threadIdx.x==0) {
    //     printf("\n TId[%d] ", threadIdx.x);
    //     printf(" WId[%u] ", warp_id);
    //     printf(" LId[%u] ", lane_id);
    //     printf(" WperG[%u] ", warps_per_grid);
    //     printf(" wTot[%u] ", warp_total);
    //     printf(" rep[%d] ", STRIDE_64K/sizeof(float)/32);
    // }

    for( ; warp_id < warp_total; warp_id += warps_per_grid) {
        #pragma unroll//告诉编译器任意展开并行等都是安全的
        for(int rep = 0; rep < STRIDE_64K/sizeof(float)/32; rep++) {
            size_t ind = warp_id * STRIDE_64K/sizeof(float) + rep * 32 + lane_id;
            if (ind < n) {
              x[ind] = 1.0f;
              // if(blockIdx.x==0 && threadIdx.x==0) {
              // 	printf(" \nind[%d] ", ind);
              // } 
              y[ind] = 2.0f;
            }
        }
    }
}

data prefetching: cudaMemPerfetchAsync()
预先告诉程序下一个设备是谁。这个最快。

cudaMemAdvice()系列API:
SetReadMostly、PreferredLocation、SetAccessBy等。

UM技术把device和host的内存看作同一个内存,可以用来解决很多GPU内存不够的问题。

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

cuda编程学习笔记 第二章 cuda memory management 的相关文章

  • 在 Windows 上的 Qt Creator 中编译 Cuda 代码

    几天来我一直在尝试获取在 32 位 Windows 7 系统上运行的 Qt 项目文件 我希望 需要在其中包含 Cuda 代码 这种组合要么非常简单 以至于没有人愿意在网上放一个例子 要么非常困难 似乎没有人成功 不管怎样 我发现的唯一有用的
  • 使用内置显卡,没有NVIDIA显卡,可以使用CUDA和Caffe库吗?

    使用内置显卡 没有 NVIDIA 显卡 可以使用 CUDA 和 Caffe 库吗 我的操作系统是 ubuntu 15 CPU为 Intel i5 4670 3 40GHz 4核 内存为12 0GB 我想开始学习深度学习 CUDA 适用于 N
  • CUDA:如何检查计算能力是否正确?

    使用较高计算能力编译的 CUDA 代码将在计算能力较低的设备上完美执行很长一段时间 然后有一天在某些内核中默默地失败 我花了半天时间追寻一个难以捉摸的错误 结果发现构建规则已经sm 21而该设备 Tesla C2050 是2 0 是否有任何
  • cudaMemcpyToSymbol 与 cudaMemcpy [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我试图找出
  • 用于类型比较的 Boost 静态断言

    以下问题给我编译器错误 我不知道如何正确编写它 struct FalseType enum value false struct TrueType enum value true template
  • Cuda Bayer/CFA 去马赛克示例

    我编写了一个 CUDA4 Bayer 去马赛克例程 但它比在 16 核 GTS250 上运行的单线程 CPU 代码慢 块大小是 16 16 图像暗淡是 16 的倍数 但更改此值并不会改善它 我做了什么明显愚蠢的事情吗 calling rou
  • 寻找 CUDA 中的最大值

    我正在尝试在 CUDA 中编写代码来查找最大值 对于给定的一组数字 假设您有 20 个数字 并且内核在 2 个块 每块 5 个线程 上运行 现在假设 10 个线程同时比较前 10 个值 并且thread 2找到最大值 因此线程 2 正在更新
  • “计算能力”是什么意思? CUDA?

    我是CUDA编程新手 对此了解不多 您能告诉我 CUDA 计算能力 是什么意思吗 当我在大学服务器上使用以下代码时 它向我显示了以下结果 for device 0 device lt deviceCount device cudaDevic
  • CUDA素数生成

    当数据大小增加超过 260k 时 我的 CUDA 程序停止工作 它不打印任何内容 有人能告诉我为什么会发生这种情况吗 这是我的第一个 CUDA 程序 如果我想要更大的素数 如何在 CUDA 上使用大于 long long int 的数据类型
  • cuda 共享内存 - 结果不一致

    我正在尝试并行缩减以对 CUDA 中的数组求和 目前我传递一个数组来存储每个块中元素的总和 这是我的代码 include
  • Visual Studio - 过滤掉 nvcc 警告

    我正在编写 CUDA 程序 但收到令人讨厌的警告 Warning Cannot tell what pointer points to assuming global memory space 这是来自 nvcc 我无法禁用它 有没有办法过
  • 如何在 Visual Studio 2010 中设置 CUDA 编译器标志?

    经过坚持不懈的得到error identifier atomicAdd is undefined 我找到了编译的解决方案 arch sm 20旗帜 但是如何在 VS 2010 中传递这个编译器标志呢 我已经尝试过如下Project gt P
  • 如何并行从数组中删除零值

    如何使用 CUDA 并行有效地从数组中删除零值 有关零值数量的信息是预先可用的 这应该可以简化这项任务 重要的是数字必须保持源数组中的顺序 当被复制到结果数组时 Example 该数组将例如包含以下值 0 0 19 7 0 3 5 0 0
  • 运行时 API 应用程序中的 cuda 上下文创建和资源关联

    我想了解如何在 cuda 运行时 API 应用程序中创建 cuda 上下文并与内核关联 我知道这是由驱动程序 API 在幕后完成的 但我想了解一下创作的时间线 首先 我知道 cudaRegisterFatBinary 是第一个 cuda a
  • 使用 CUDA 进行逐元素向量乘法

    我已经在 CUDA 中构建了一个基本内核来执行逐元素两个复向量的向量 向量乘法 内核代码插入如下 multiplyElementwise 它工作正常 但由于我注意到其他看似简单的操作 如缩放向量 在 CUBLAS 或 CULA 等库中进行了
  • 如何在cmake中添加cuda源代码的定义

    我使用的是 Visual Studio 2013 Windows 10 CMake 3 5 1 一切都可以使用标准 C 正确编译 例如 CMakeLists txt project Test add definitions D WINDOW
  • 在 cudaFree() 之前需要 cudaDeviceSynchronize() 吗?

    CUDA 版本 10 1 帕斯卡 GPU 所有命令都发送到默认流 void ptr cudaMalloc ptr launch kernel lt lt lt gt gt gt ptr cudaDeviceSynchronize Is th
  • TensorRT 多线程

    我正在尝试使用 python API 来使用 TensorRt 我试图在多个线程中使用它 其中 Cuda 上下文与所有线程一起使用 在单个线程中一切正常 我使用 docker 和 tensorrt 20 06 py3 图像 onnx 模型和
  • 从 CUDA 设备写入输出文件

    我是 CUDA 编程的新手 正在将 C 代码重写为并行 CUDA 新代码 有没有一种方法可以直接从设备写入输出数据文件 而无需将数组从设备复制到主机 我假设如果cuPrintf存在 一定有地方可以写一个cuFprintf 抱歉 如果答案已经
  • cudaMemcpy() 与 cudaMemcpyFromSymbol()

    我试图找出原因cudaMemcpyFromSymbol 存在 似乎 symbol func 可以做的所有事情 nonSymbol cmd 也可以做 symbol func 似乎可以轻松移动数组或索引的一部分 但这也可以使用 nonSymbo

随机推荐