CUDA 学习记录

news2024/11/18 5:43:26

1.关于volatile:

对于文章中这个函数,

__global__ void reduceUnrollWarps8 (int *g_idata, int *g_odata, unsigned int n)
{
    // set thread ID
    unsigned int tid = threadIdx.x;
    unsigned int idx = blockIdx.x * blockDim.x * 8 + threadIdx.x;

    // convert global data pointer to the local pointer of this block
    int *idata = g_idata + blockIdx.x * blockDim.x * 8;

    // unrolling 8
    if (idx + 7 * blockDim.x < n)
    {
        int a1 = g_idata[idx];
        int a2 = g_idata[idx + blockDim.x];
        int a3 = g_idata[idx + 2 * blockDim.x];
        int a4 = g_idata[idx + 3 * blockDim.x];
        int b1 = g_idata[idx + 4 * blockDim.x];
        int b2 = g_idata[idx + 5 * blockDim.x];
        int b3 = g_idata[idx + 6 * blockDim.x];
        int b4 = g_idata[idx + 7 * blockDim.x];
        g_idata[idx] = a1 + a2 + a3 + a4 + b1 + b2 + b3 + b4;
    }

    __syncthreads();

    // in-place reduction in global memory
    for (int stride = blockDim.x / 2; stride > 32; stride >>= 1)
    {
        if (tid < stride)
        {
            idata[tid] += idata[tid + stride];
        }

        // synchronize within threadblock
        __syncthreads();
    }

    // unrolling warp
    if (tid < 32)
    {
        volatile int *vmem = idata;
        vmem[tid] += vmem[tid + 32];
        vmem[tid] += vmem[tid + 16];
        vmem[tid] += vmem[tid +  8];
        vmem[tid] += vmem[tid +  4];
        vmem[tid] += vmem[tid +  2];
        vmem[tid] += vmem[tid +  1];
    }

    // write result for this block to global mem
    if (tid == 0) g_odata[blockIdx.x] = idata[0];
}

在  //unrolling wrap 之前的for循环完成后,只剩下idata[0] 到 idata[63](共64个元素)的数据还没有进行加和。

之前的疑问是 最后的if语句块内为什么会完成这个操作而不出问题:

因为一个线程束内的线程会进行同步,所以if里的语句是,所有线程执行第一条语句,都执行完了,再执行第二条语句。

然后关于volitale ,大家都说是禁止编译器优化,我的理解是:

如果没有volatile,各个线程写寄存器的时候是有同步的,从寄存器写到共享内存是没有同步的。(不过在我这里,去掉volatile结果也是对的。。。)

2.关于延迟隐藏

目前个人理解就是让一个线程尽可能多做事。

3.关于如何获得最大线程束 

参考:【精选】CUDA编程:笔记2_线程束_longlongqin的博客-CSDN博客

little法则给出了下面的计算公式"所需线程束 = 延迟 × 吞吐量 

带宽:一般指的是理论峰值,最大每个时钟周期能执行多少个指令;

吞吐量:是指实际操作过程中每分钟处理多少个指令。

每次想到还是看书吧。 

一个WRAP访存周期是T,刚好是Wrap处理指令时间周期t的K倍,只需要K个wrap就能隐藏访存带来的延迟。

得到最大线程束数量还要减少分支

4.选择合适的网格和块:

有个工具包(同学说不能使了,但是应该也提供了别的方法)。

4.什么是事务内存

参考:初识事务内存(Transactional Memory) - 知乎

个人理解:比u锁更好的具有原子性的互斥手段。 

5.在GPU上只有内存加载操作可以被缓存,内存存储操作不能被缓存。

内存加载操作:从全局内存或其他内存读数据加载到寄存器或缓存中。

内存存储操作:将数据从寄存器或缓存写入到内存

线程加载数据时,如果缓存中有数据,可以直接从缓存中加载。而存储操作通常不能被缓存,因为要保证数据的一致性,必须及时更新内存中的数据,而不能依赖于缓存。

6.对于固定内存和零拷贝内存

当传输大数据时,使用固定内存:cudaError_t cudaMallocHost(void **devPtr, size_t count);

cudaError_t cudaFreeHost(void *ptr);

如果想要共享主机和设备端的少量数据,使用零拷贝内存:

cudaErroer_t cudaHostAlloc(void **pHost, size_t count, unsigned int flags);

cudaFreeHost()

使用下列函数获取映射到固定内存的设备指针:

cudaError_t cudaHostGetDevicePointer(void **pDevice, void *pHost, unsigned int flags);

    // part 2: using zerocopy memory for array A and B
    // allocate zerocpy memory
    CHECK(cudaHostAlloc((void **)&h_A, nBytes, cudaHostAllocMapped));
    CHECK(cudaHostAlloc((void **)&h_B, nBytes, cudaHostAllocMapped));

    // initialize data at host side
    initialData(h_A, nElem);
    initialData(h_B, nElem);
    memset(hostRef, 0, nBytes);
    memset(gpuRef,  0, nBytes);

    // pass the pointer to device
    CHECK(cudaHostGetDevicePointer((void **)&d_A, (void *)h_A, 0));
    CHECK(cudaHostGetDevicePointer((void **)&d_B, (void *)h_B, 0));

    // add at host side for result checks
    sumArraysOnHost(h_A, h_B, hostRef, nElem);

    // execute kernel with zero copy memory
    sumArraysZeroCopy<<<grid, block>>>(d_A, d_B, d_C, nElem);

    // copy kernel result back to host side
    CHECK(cudaMemcpy(gpuRef, d_C, nBytes, cudaMemcpyDeviceToHost));

    // check device results
    checkResult(hostRef, gpuRef, nElem);

    // free  memory
    CHECK(cudaFree(d_C));
    CHECK(cudaFreeHost(h_A));
    CHECK(cudaFreeHost(h_B));

有了虚拟内存寻址(UVA)后,由cudaHostAlloc()分配的固定主机内存具有相同的主机和设备指针,可以将返回的指针直接传递给核函数:

cudaHostAlloc((void **)&h_A, nBytes, cudaHostAllocMapped);
cudaHostAlloc((void **)&h_B, nBytes, cudaHostAllocMapped);

initialData(h_A, nElem);
initialData(h_B, nElem);

sumArrayZeroCopy<<<grid, block>>>(h_A, h_B, d_C, nElem);

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

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

相关文章

李m圆申论

听话出活 3小时 /处理7500字 /一共5题 /写出2200字 字写得好看点&#xff0c;符号也算字数&#xff0c;占一个格 基本思路&#xff1a;考什么范围答什么 。。。落后&#xff1b;资源闲置、缺乏 申论&#xff1a; 作文题&#xff1a;举例子 处理材料 摘抄&#xff1a; 有人出…

《数据结构、算法与应用C++语言描述》-队列的应用-电路布线问题

《数据结构、算法与应用C语言描述》-队列的应用-电路布线问题 问题描述 在 迷宫老鼠问题中&#xff0c;可以寻找从迷宫入口到迷宫出口的一条最短路径。这种在网格中寻找最短路径的算法有许多应用。例如&#xff0c;在电路布线问题的求解中&#xff0c;一个常用的方法就是在布…

Linux进程(三)--进程切换命令行参数

继上回书Linux进程概念&#xff08;二&#xff09;--进程状态&进程优先级&#xff0c;我们在了解了Linux进程状态和优先级的概念&#xff0c;初步掌握了进程状态的相关知识&#xff0c;最终&#xff0c;我们以Linux进程的优先级&#xff0c;引出了一些其他的概念&#xff1…

非平稳信号分析和处理、STFT的瞬时频率研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

高校教务系统登录页面JS分析——华南理工大学

高校教务系统密码加密逻辑及JS逆向 本文将介绍高校教务系统的密码加密逻辑以及使用JavaScript进行逆向分析的过程。通过本文&#xff0c;你将了解到密码加密的基本概念、常用加密算法以及如何通过逆向分析来破解密码。 本文仅供交流学习&#xff0c;勿用于非法用途。 一、密码加…

可以更改字体颜色的便签备忘录工具选择用哪个

日常添加笔记记录是一个非常好的习惯&#xff0c;通过笔记来记录一些重要的内容一方面可以帮助大家回顾过去的相关记录&#xff0c;另一方面如果记录的笔记是有关学习类的&#xff0c;还有助于大家随时查看记录的笔记。 多数时候记录笔记内容大家通常会选择一些比较方便易操作…

Spring中配置文件参数化

目录 一、什么是配置文件参数化 二、配置文件参数化的开发步骤 一、什么是配置文件参数化 配置文件参数化就是将Spring中经常需要修改的字符串信息&#xff0c;转移到一个更小的配置文件中。那么为什么要进行配置文件参数化呢&#xff1f;我们看一个代码 <bean id"co…

Chrome插件精选 — 扩展管理插件

Chrome实现同一功能的插件往往有多款产品&#xff0c;逐一去安装试用耗时又费力&#xff0c;在此为某一类型插件挑选出比较好用的一款或几款&#xff0c;尽量满足界面精致、功能齐全、设置选项丰富的使用要求&#xff0c;便于节省一个个去尝试的时间和精力。 1. 扩展管理器 下…

推荐《全职猎人》

电视动画《全职猎人》是由MADHOUSE公司制作的长篇电视动画&#xff0c;改编自日本漫画家富坚义博创作的同名漫画。该动画于2011年10月2日—2014年9月23日在日本电视网协议会首播&#xff0c;全148话。 剧场版动画《全职猎人&#xff1a;绯色的幻影》和《全职猎人&#xff1a;最…

Influence on Social media(素论+思维)

传送门&#xff1a;nefu_10-18 - Virtual Judge (vjudge.net) 思路&#xff1a; 每次给n个数&#xff0c;判断每个数的除数总数是否为奇素数。 对于整数&#xff1a;可质因子分解&#xff0c;,除数总数为&#xff08;i11&#xff09;*(i21)*(i31).... 若除数总数为奇素数&a…

golang笔记17--编译调试go源码

golang笔记17--编译调试go源码 前置条件编译源码在 fmt 包中加自定义函数说明 当前go语言越来越流行了&#xff0c;各大厂商都有加大go工程师的需求&#xff0c;作为go语言的学习者&#xff0c;我们除了要了解如何使用go语言外&#xff0c;也有必要了解一下如何编译、调试go源码…

双网关备份(bfd+VRRP+策略路由配置)企业网搭建

设备选型 vlan规划 Ip地址规划 产品名字 产品型号 设备命名 登录密码 路由器 Ar2220 Dianxin 123456 路由器 Ar2220 Dianxin 123456 路由器 Ar2220 Liantong 123456 路由器 Ar2220 R3 123456 交换机 S5700 S1 123456 交换机 S5700 S2 123456 交换机…

第十五章:输入输出流I/O

15.1&#xff1a;输入/输出流 文件类&#xff1a;File 字节流&#xff1a;InputStream&#xff1a;入 OutputStream&#xff1a;出 字符流&#xff1a;Reader&#xff1a;入 Writer&#xff1a;出 15.1.1 输入流 InputStream类是字节输入流的抽象类&#xff0c;所有字节流…

ubuntu终端命令行下如何使用NetworkManager(netplan)来配置wifi网络

最近在给家里折腾一个文件共享服务器给家里的小米摄像头保存监控视频用。树莓派太贵了&#xff0c;找来找去发现香橙派orangepi zero3 是最低成本的替代解决方案&#xff08;网络足够快&#xff0c;CPU的IO能力足够强&#xff09;&#xff0c;香橙派orangepi zero3的操作系统是…

《C语言图形界面-系统开发》专栏介绍 专栏目录

《C语言图形界面-系统开发》介绍及目录 基本介绍 本项目是一个基于EasyX图形库的C语言图书管理系统。 界面优美高级代码结构设计合理注释详尽清晰 本专栏是一个详尽到完全贴近C语言初学者的教程&#xff0c;完整代码 配套教程&#xff0c;完全不用担心学不会的问题。 项目展…

FPGA的通用FIFO设计verilog,1024*8bit仿真,源码和视频

名称&#xff1a;FIFO存储器设计1024*8bit 软件&#xff1a;Quartus 语言&#xff1a;Verilog 本代码为FIFO通用代码&#xff0c;其他深度和位宽可简单修改以下参数得到 reg [7:0] ram [1023:0];//RAM。深度1024&#xff0c;宽度8 代码功能&#xff1a; 设计一个基于FPGA…

EDUSRC--简单打穿某985之旅

免责声明&#xff1a; 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直…

AN动画基础——父子级关系

【AN动画基础——父子级关系】 父子级关系基础动画实战&#xff0c;行星的自转与公转 本篇内容&#xff1a;了解父子级关系 重点内容&#xff1a;父子级关系做动画 工 具&#xff1a;Adobe Animate 2022 父子级关系 在动画中&#xff0c;父子级关系通常用于控制对象之间的层次…

盘点数据采集中14种常见的反爬策略

引言 随着互联网的飞速发展, 爬虫技术不断演进, 为数据获取和信息处理提供了强大支持。然而, 滥用爬虫和恶意爬取数据的行为日益增多, 引发了反爬虫技术的兴起。在这场看似永无止境的 技术较量 中, 爬虫与反爬虫技术相互博弈、角力。本文将简单过下目前已知的几种反爬策略, 旨…

10.16课上,煎饼排序(选择排序实现),冒泡排序,快速排序

煎饼排序 第一步找剩余数组里的最大值&#xff0c;然后从头到这里翻转一次&#xff0c;这样最大值就到了开头&#xff0c;再把开头从当前结尾翻转一次&#xff0c;就把当前的最大值翻转到了最后 class Solution { public:vector<int> pancakeSort(vector<int>&am…