3.2 MAPPING THREADS TO MULTIDIMENSIONAL DATA

news2024/11/27 10:44:23

1D、2D或3D线程组织的选择通常基于数据的性质。图片是2D像素阵列。使用由2D块组成的2D网格通常可以方便地处理图片中的像素。图3.2显示了处理76×62图片P的这种安排(水平或x方向为76像素,垂直或y方向为62像素)。假设我们决定使用16 x 16块,x方向有16个线程,y方向有16个线程。我们需要x方向的5个块和y方向的4个块,结果是5个x 4=20个块,如图3.2所示,沉重的线条标志着block的边界。阴影区域描绘了覆盖像素的线程。很容易验证是否可以用公式识别由块(1,0)的线程(0,0)处理的Pin元素:
在这里插入图片描述
在这里插入图片描述
请注意,我们在x方向有4个额外的线程,在y方向有2个额外的线程——也就是说,我们将生成80×64个线程来处理76×62像素。这种情况类似于图2.11中1D内核vecAddKernel处理1000元素向量的情况。使用四个256线程块。回想一下,需要一个if语句来防止额外的24个线程生效。类似地,我们应该期望图片处理内核函数将有if语句来测试线程索引threadldx.x和threadldx.y是否在有效的像素范围内。

假设主机代码使用整数变量m来跟踪x方向的像素数,另一个整数变量n来跟踪y方向的像素数。我们进一步假设输入图片数据已复制到设备内存中,可以通过指针变量d_Pin访问。输出图片已分配到设备内存中,可以通过指针变量d_Pout访问。以下主机代码可用于启动2D内核colorToGreyscaleConversion来处理图片,如下所示:

dim3 dimGrid(ceil(m/16.0), ceil(n/16.0), 1);
dim3 dimBlock(16, 16, 1);
colorToGreyscaleConversion<<<dimGrid,dimBlock>>>(d_Pin,d_Pout,m,n);

在本例中,为了简单起见,我们假设块的尺寸固定在16×16。与此同时,网格的尺寸取决于图片的尺寸。为了处理2000×1500(3百万像素)的图片,我们将生成11,750个块——x方向的125个,y方向的94个。在内核函数中,对gridDim.x、gridDim.y、blockDim.x和blockDim.y的引用将分别导致125、94、16和16。

记忆空间
内存空间是处理器如何在现代计算机中访问其内存的简化视图。它通常与每个正在运行的应用程序相关联。应用程序要处理的数据和为应用程序执行的指令存储在其内存空间中的位置。通常,每个位置可以容纳一个字节,并且有一个地址。需要多个字节的变量(浮点为4字节,双字节为8字节)存储在连续的字节位置。处理器生成起始地址(起始字节位置的地址)和从内存空间访问数据值时所需的字节数。
内存空间中的位置类似于电话系统中的电话,每个人都有一个唯一的电话号码。大多数现代计算机至少有4G字节大小的位置,其中每个G为1,073,741,824(2^30)。所有位置都标有从0到最大数字的地址。每个位置只有一个地址;因此,我们说内存空间有一个“扁平”的组织。因此,所有多维数组最终都会“扁平化”成等效的一维数组。C程序员可以使用多维语法访问多维数组的元素,而编译器将这些访问转换为指向数组初始元素的基指针,以及从这些多维索引计算的偏移量。

在显示内核代码之前,我们首先需要了解C语句如何访问动态分配的多维数组的元素。理想情况下,我们希望以二维数组的方式访问d_Pin,其中行j和列i的元素可以作为d_Pin[j][i]访问。然而,CUDA C开发所依据的ANSI C标准要求在编译时知道d_Pin中的列数,以便将d_Pin作为2D数组访问。不幸的是,对于动态分配的数组,此信息在编译器时是未知的。事实上,使用动态分配数组的部分原因是允许这些数组的大小和尺寸在运行时根据数据大小而变化。因此,根据设计,在编译时,动态分配的二维数组中的列数信息是未知的。因此,程序员需要将动态分配的二维数组显式线性化或“flatten”为当前CUDA C中等效的一维数组。较新的C99标准允许动态分配数组的多维语法。未来的CUDA C版本可能支持动态分配数组的多维语法。

实际上,由于在现代计算机中使用了“平面”内存空间,C中的所有多维阵列都是线性化的(见“内存空间”侧边栏)。在静态分配的数组中,编译器允许程序员使用更高维的索引语法,如d_Pin[j][i] 来访问他们的元素。在引擎盖下,编译器将它们线性化为等效的一维数组,并将多维索引语法转换为一维偏移量。在动态分配数组中,由于在编译时缺乏维度信息,当前的CUDA C编译器将此类翻译工作留给了程序员。

二维数组至少可以通过两种方式线性化。一种方法是将同一行的所有元素放置到连续的位置。然后将行一个接一个地放置在内存空间中。这种安排被称为行主要布局,如图3.3.所示。为了提高可读性,我们将使用Mji来表示j”行和i列的M元素。 P j , i P_{j,i} Pj,i等价于C表达式M[j][i],但可读性稍高。图3.3说明了4×4矩阵M如何线性化为16个元素的一维数组,首先是0行的所有元素,然后是第1行的四个元素,以此为例。因此,j行和i列中M的一维等效索引是j4 + i。j4项跳过行j之前行的所有元素。然后,i术语在j行的部分中选择正确的元素。M2.1的一维指数为24 + 1 = 9,如图所示。3.3,其中Mg是M2,1的一维等价物。这个过程展示了C编译器将二维数组线性化的方式。 M 2 , 1 M_{2,1} M2,1的一维指数为24 + 1 = 9,如图3.3所示,其中 M 9 M_9 M9 M 2 , 1 M_{2,1} M2,1的一维等价物。这个过程展示了C编译器将二维数组线性化的方式。
在这里插入图片描述
线性化二维数组的另一种方法是将同一列的所有元素放入连续的位置。然后将列一个接一个地放置在内存空间中。这种安排,称为列主要布局,由FORTRAN编译器使用。二维数组的列-主要布局等同于其转置形式的行-主要布局。之前主要编程经验是FORTRAN的读者应该知道,CUDA C使用行主要布局,而不是列主要布局。此外,许多为FORTRAN程序设计的C库使用列主要布局来匹配FORTRAN编译器布局。因此,这些库的手册页,如基本线性代数子程序(BLAS)(见“线性代数函数”侧边栏),通常指示用户从C程序调用这些库时转置输入数组。

线性代数函数
线性代数运算广泛用于科学和工程应用。BLAS是发布执行基本代数运算的库的事实标准,包括三个级别的线性代数函数。随着水平的增加,该函数执行的操作数量也会增加。1级函数执行形式为y =ax + y的向量操作,其中x和y是向量,a是标量。我们的向量加法示例是具有a=1的1级函数的特殊情况。2级函数执行形式为y = αAx + βy的矩阵向量运算,其中A是矩阵,x和y是向量,a是裸标量。我们将研究稀疏线性代数中2级函数的一种形式。3级函数执行C = αAB + βC形式的矩阵矩阵运算,其中A、B、C是矩阵,a、b是标量。我们的矩阵-矩阵乘法示例是3级函数的特殊情况,其中a=1和B=0。这些BLAS函数被用作线性系统求解器和特征值分析等高级代数函数的基本构建块。正如我们稍后将讨论的那样,在顺序和并行计算机中,BLAS函数的不同实现的性能可能因数量级而异。

我们现在准备研究图3.4.中所示的colorToGreyscaleConversion的源代码。内核代码使用公式
*0.21+g*0.72+b*0.07
将每个颜色像素转换为灰度对应物。

在水平方向上可以找到总共的blockDim.xgridDim.x线程。与vecAddKernel示例一样,表达式Col=blockIdx.xblockDim.x+threadIdx.x生成从0到blockDim.xgridDim.x-1的每个整数值。我们知道gridDim.xblockDim.x大于或等于宽度(从主机代码传递的m值)。我们的线程数量至少与水平方向的像素数一样多。同样,我们知道线程至少与垂直方向的像素数一样多。因此,只要我们测试并确保只有具有行和Col值的线程在范围内——即(Col<width)&&(Row<height)——我们就可以覆盖图片中的每个像素。
在这里插入图片描述
鉴于每行都有宽度像素,因此我们可以为行Row和列Col的像素生成一维索引为Row*width+Col。这个一维索引greyOffset是Pout的像素索引,因为输出灰度图像中的每个像素都是一个字节(无符号字符)。通过使用我们的76×62图像示例,Pout像素的线性化一维索引由块(1,0)的线程(0,0)计算,公式为:
在这里插入图片描述
至于Pin,我们将灰色像素索引乘以3,因为每个像素存储为(r,g,b),每个像素等于一个字节。生成的rgboffset给出了Pin数组中颜色像素的起始位置。我们从Pin数组的三个连续字节位置读取r、g和b值,执行灰度像素值的计算,并使用greyOffset将该值写入Pout数组。在我们的76×62图像示例中,引脚像素的线性化一维索引由块(1,0)的线程(0,0)计算,公式如下:
在这里插入图片描述
在这里插入图片描述
正在访问的数据是三个字节,从字节索引3648开始。

图3.5说明了在处理我们的76×62示例时执行colorToGreyscaleConversion。假设我们使用16×16块,启动colorToGreyscaleConversion会生成80 x 64线程。网格将有20个块——5个水平方向,4个垂直方向。块的执行行为将分为四种不同情况之一,在图3.5.中描述为四个阴影区域。

第一个区域,在图3.5中标记为“1”,由属于覆盖图片中大部分像素的12个块的线程组成。这些线程的Col和Row值都在范围内;所有这些线程都将通过if-statement测试,并在图片的阴影严重区域处理像素——即每个块中的所有16×16=256线程都将处理像素。第二个区域,在图中标记为“2”。3.5,包含属于覆盖图片右上角像素的中等阴影区域中三个块的线程。虽然这些线程的行值总是在范围内,但一些Col值超过m值(76)。原因是水平方向的线程数总是程序员选择的blockDim.x值的倍数(在本例中为16)。覆盖76像素所需的16的最小倍数是80。因此,每行中的12个线程将具有范围内的Col值,并将处理像素。与此同时,每行中的4个线程将具有不在范围内的Col值,因此无法满足if-statement条件。这些线程不会处理任何像素。总体而言,每个块中的16×16=256个线程中的12×16=192将处理像素。

第三个区域,在图中标记为“3”。3.5,占了3个左下角的blocks,覆盖了图片中的中等阴影区域。虽然这些线程的Col值总是在范围内,但一些行值超过m值(62)。原因是垂直方向的线程数总是程序员选择的blockDim.y值的倍数(在这种情况下是16)。覆盖62的16的最小倍数是64。因此,每列中的14个线程将具有范围内的行值,并将处理像素。与此同时,每列中的2个线程将失败区域2的if-statement,并且不会处理任何像素。在256个线程中,16×14 = 224将处理像素。第四个区域,在图中标记为“4”。3.5,包含覆盖图片右下角、轻度阴影区域的线程。在前14行中的每行中,4个线程的Col值将处于范围之外,类似于区域2。该块的整个底部两行将具有范围之外的行值,类似于区域“3”。因此,16 × 16 = 256个线程中只有14 x 12 = 168将处理像素。

当我们线性化数组时,我们可以通过包括另一个维度,轻松地将2D数组的讨论扩展到3D数组。这是通过将数组的每个“plane”一个接一个地放入地址空间来实现的。假设程序员使用变量m和n来跟踪3D数组中的列数和行数。程序员在启动内核时还需要确定b1ockDim.z和gridDim.z的值。在内核中,数组索引将涉及另一个全局索引:

int Plane = blockIdx.z*blockDim.z + threadIdx.z

对三维数组P的线性访问将以P[Planemn+Row*m+Col]的形式进行。处理3D P阵列的内核需要检查所有三个全局索引(Plane、Row和Co1)是否都在数组的有效范围内。

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

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

相关文章

桌面图标变成白色文件?学会这4个方法,轻松解决!

“不知道为什么&#xff0c;我有些文件夹直接保存在电脑桌面了&#xff0c;但是今天查看的时候却发现它们变成了白色的文件。有什么方法可以解决这个问题吗&#xff1f;” 在使用电脑时&#xff0c;可能由于各种原因&#xff0c;会出现桌面图标变成白色文件的情况。这不仅会让用…

听GPT 讲Rust源代码--compiler(36)

File: rust/compiler/rustc_middle/src/mir/graphviz.rs 在Rust源代码中&#xff0c;rust/compiler/rustc_middle/src/mir/graphviz.rs文件的作用是生成MIR&#xff08;Mid-level Intermediate Representation&#xff09;的图形可视化表示。MIR是Rust编译器中间表示的一种形式…

如何解决海量数据的问题

近年来&#xff0c;高并发、分布式以及大数据成了后端开发者绕不开的话题&#xff0c;招聘软件上几呼都写着有高并发、大数据等项目经历优先时。很多人实际项目往往都是 CRUD&#xff0c;也没机会接触到这些场景啊。 但是&#xff0c;有位伟人曾经说过&#xff1a;没有条件&am…

九、HTML头部<head>

一、HTML头部<head> 1、<title>- 定义了HTML文档的标题 使用 <title> 标签定义HTML文档的标题 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>我的 HTML 的第一页</title> </head><b…

ant-design-vue的日期组件a-range-picker赋值的问题

在使用ant-design-vue的日期组件时&#xff0c;总是会碰到赋值问题&#xff0c;习惯性的赋值就是直接给日期组件的变量赋值字符串类型&#xff0c;如下 // html部分 <a-range-picker v-model"dateValue" :format"YYYY-MM-DD"/> // js部分 data() {r…

2024年大数据不完全预测

人工智能的进步可能是2024年的主要推动力&#xff0c;也凸显出大数据的挑战——如何存储、管理、管理和使用大数据——从未如此紧迫。&#xff0c;因为如果作为基石的数据失控&#xff0c;人工智能就没有意义了。当然反之亦然。 人工智能的进步可能是2024年的主要推动力&#…

1999-2022年上市公司微观企业劳动生产率数据(原始数据+计算代码+处理结果)

1999-2022年上市公司微观企业劳动生产率数据&#xff08;原始数据计算代码处理结果&#xff09; 1、时间&#xff1a;1999-2022年 2、来源&#xff1a;原始数据整理自csmar 3、指标&#xff1a;证券代码&#xff0c;证券简称、员工人数&#xff0c;营业收入 4、范围&#x…

C++ 学习系列 -- tuple 原理

一 可变参数模板 variadic template 前面的章节 C 学习系列 -- 模板 template-CSDN博客 我们介绍了 c 中的模板概念&#xff0c;本章则在其基础上介绍了新的概念 可变参数模板 variadic template &#xff0c;顾名思义&#xff0c;可变参数模板意思为模板参数的类型与数量是变…

浅谈智能照明系统调试阶段节能方案的探究与产品选型

贾丽丽 安科瑞电气股份有限公司 上海嘉定 201801 【摘要】针对当今智能照明系统调试完成前能源浪费的问题&#xff0c;本文结合工程案例&#xff0c;分析研究了智能照明系统调试阶段的节能方法&#xff0c;提出了采用时间控制器来解决能源及人工浪费等问题的方式。实践证明&a…

微众区块链观察节点的架构和原理 | 科普时间

践行区块链公共精神&#xff0c;实现更好的公众开放与监督&#xff01;2023年12月&#xff0c;微众区块链观察节点正式面向公众开放接入功能。从开放日起&#xff0c;陆续有多个观察节点在各地运行&#xff0c;同步区块链数据&#xff0c;运行区块链浏览器观察检视数据&#xf…

Kafka(六)消费者

目录 Kafka消费者1 配置消费者bootstrap.serversgroup.idkey.deserializervalue.deserializergroup.instance.idfetch.min.bytes1fetch.max.wait.msfetch.max.bytes57671680 (55 mebibytes)max.poll.record500max.partition.fetch.bytessession.timeout.ms45000 (45 seconds)he…

【STM32】STM32学习笔记-DMA数据转运+AD多通道(24)

00. 目录 文章目录 00. 目录01. DMA简介02. DMA相关API2.1 DMA_Init2.2 DMA_InitTypeDef2.3 DMA_Cmd2.4 DMA_SetCurrDataCounter2.5 DMA_GetFlagStatus2.6 DMA_ClearFlag 03. DMA数据单通道接线图04. DMA数据单通道示例05. DMA数据多通道接线图06. DMA数据多通道示例一07. DMA数…

STM32(HAL库) CubeMX+Keil5 建立工程

STM32&#xff08;HAL库&#xff09; CubeMXKeil5 建立工程 目标选择 菜单栏 File 新建工程打开工程退出软件 Window 输出窗口的开启软件字体设置 Help 软件帮助文档检查软件更新管理MCU 已存在工程&#xff08;Existing Projects&#xff09; 最近打开过的工程(Recent Open…

如何科学评价视频生成模型?AIGCBench:全面可扩展的视频生成任务基准来了!

AIGC领域正迅速发展&#xff0c;特别是在视频生成方面取得了显著进展。本文介绍了AIGCBench&#xff0c;这是一个首创的全面而可扩展的基准&#xff0c;旨在评估各种视频生成任务&#xff0c;主要关注图像到视频&#xff08;I2V&#xff09;生成。AIGCBench解决了现有基准的局限…

苹果显示连接iTunes是什么意思?你知道吗?答案来了!

相信使用苹果手机的小伙伴都听说过iTunes软件&#xff0c;但是可能还有小部分人不知道iTunes是什么&#xff0c;以及苹果设备上显示连接itunes是什么意思。对于使用iTunes进行数据备份、恢复等操作的用户来说&#xff0c;出现这个提示意味着您的苹果设备已经与电脑成功连接&…

vue-springboot基于java的实验室安全考试系统

本系统为用户而设计制作实验室安全考试系统&#xff0c;旨在实现实验室安全考试智能化、现代化管理。本实验室安全考试管理自动化系统的开发和研制的最终目的是将实验室安全考试的运作模式从手工记录数据转变为网络信息查询管理&#xff0c;从而为现代管理人员的使用提供更多的…

【Docker基础一】Docker安装Elasticsearch,Kibana,IK分词器

安装elasticsearch 下载镜像 查看版本&#xff1a;Elasticsearch Guide [8.11] | Elastic # 下载镜像 docker pull elasticsearch:7.17.16 # 查看镜像是否下载成功 docker images创建网络 因为需要部署kibana容器&#xff0c;要让es和kibana容器互联 # 创建一个网络&…

并发(10)

目录 61.ReentrantReadWriteLock底层读写状态如何设计的&#xff1f; 62.读锁和写锁的最大数量是多少&#xff1f; 63.本地线程计数器ThreadLocalHoldCounter是用来做什么的&#xff1f; 64.写锁的获取与释放是怎么实现的&#xff1f; 65.读锁的获取与释放是怎么实现的&…

【算法】递归算法理解(持续更新)

这里写目录标题 一、递归算法1、什么情况下可以使用递归&#xff1f;2、递归算法组成部分3、案例&#xff1a;求n的阶乘4、编写一个递归函数来计算列表包含的元素数。5、通过递归找到列表中最大的数字。6、通过递归的方式实现二分查找算法。 一、递归算法 递归&#xff08;Rec…

浅谈LCD屏幕引脚定义识别

学习单片机&#xff0c;总要驱动LCD屏幕&#xff0c;但是对于没有引脚定义的LCD屏幕该如何应对&#xff1f; 本人研究不深&#xff0c;只谈体会。 比如下面这款屏幕 一、第一种方法 百度大法查引脚定义。查询条件可以是FPC上的丝印&#xff0c;或者是屏幕的尺寸&#xff0c;引脚…