将数据上传到共享内存中用于卷积核

2023-12-28

我在理解评论中提到的批量加载时遇到一些困难。为了计算像素中的卷积,大小为 5 的掩模必须以该特定像素为中心。图像被分成图块。应用卷积掩模后的这些图块是最终输出图块,其大小为TILE_WIDTH*TILE_WIDTH。对于属于输出图块边界的像素,当该图块属于图像的边界时,掩模必须从相邻图块借用一些像素。否则,这些借用值将被分配为零。这两个步骤描述于

if (srcY >= 0 && srcY < height && srcX >= 0 && srcX < width)
    N_ds[destY][destX] = I[src];
else
    N_ds[destY][destX] = 0;

因此,共享内存阵列具有TILE_WIDTH + Mask_width - 1每边的尺寸。我不清楚代码的以下部分。

  1. The destY and destX指数。 将输出索引除以输入图块宽度意味着什么?

  2. The srcY add srcX index.
    Why destY and destX指数参与srcY add srcX index?

    srcY = blockIdx.y * TILE_WIDTH + destY - Mask_radius;
    srcX = blockIdx.x * TILE_WIDTH + destX - Mask_radius;
    
  3. 为什么在第二次加载时我们使用偏移量TILE_WIDTH * TILE_WIDTH?

  4. 一般来说,有两个载荷的直观解释是什么?

  5. 所有这些问题都可以根据下图给出一个直观的例子吗?

  6. 谢谢你!

EDIT:图像已添加。绿色是输出图块,红色是以 114 索引为中心的掩码。很明显,面具借用了不同图块的元素。 最后,该图像指的是一个通道。

Example:根据下图,我尝试编写一个示例。输出图块有blockIdx.x=1 and blockIdx.y=1基于此destY=0 and destX=0. Also,
srcY = 1*6+0-3=3, srcX = 3 and src = (3*18+3)*3+0=171。根据计算和图像示例,我们没有匹配项。在第一个共享内存位置,应该存储的值是具有全局索引的值57。上述计算有什么问题呢?有人可以帮忙吗?

#define Mask_width  5
#define Mask_radius Mask_width/2
#define TILE_WIDTH 16
#define w (TILE_WIDTH + Mask_width - 1)
#define clamp(x) (min(max((x), 0.0), 1.0))

__global__ void convolution(float *I, const float* __restrict__ M, float *P,
                            int channels, int width, int height) {
   __shared__ float N_ds[w][w];
   int k;
   for (k = 0; k < channels; k++) {
      // First batch loading
      int dest = threadIdx.y * TILE_WIDTH + threadIdx.x,
         destY = dest / w, destX = dest % w,
         srcY = blockIdx.y * TILE_WIDTH + destY - Mask_radius,
         srcX = blockIdx.x * TILE_WIDTH + destX - Mask_radius,
         src = (srcY * width + srcX) * channels + k;
      if (srcY >= 0 && srcY < height && srcX >= 0 && srcX < width)
         N_ds[destY][destX] = I[src];
      else
         N_ds[destY][destX] = 0;

      // Second batch loading
      dest = threadIdx.y * TILE_WIDTH + threadIdx.x + TILE_WIDTH * TILE_WIDTH;
      destY = dest / w, destX = dest % w;
      srcY = blockIdx.y * TILE_WIDTH + destY - Mask_radius;
      srcX = blockIdx.x * TILE_WIDTH + destX - Mask_radius;
      src = (srcY * width + srcX) * channels + k;
      if (destY < w) {
         if (srcY >= 0 && srcY < height && srcX >= 0 && srcX < width)
            N_ds[destY][destX] = I[src];
         else
            N_ds[destY][destX] = 0;
      }
      __syncthreads();

      float accum = 0;
      int y, x;
      for (y = 0; y < Mask_width; y++)
         for (x = 0; x < Mask_width; x++)
            accum += N_ds[threadIdx.y + y][threadIdx.x + x] * M[y * Mask_width + x];
      y = blockIdx.y * TILE_WIDTH + threadIdx.y;
      x = blockIdx.x * TILE_WIDTH + threadIdx.x;
      if (y < height && x < width)
         P[(y * width + x) * channels + k] = clamp(accum);
      __syncthreads();
   }
}

您的问题在概念上与我在 StackOverflow 上的第一个问题类似:移动 (BS_X+1)(BS_Y+1) BS_X 的全局内存矩阵BS_Y 线程 https://stackoverflow.com/questions/13771538/moving-a-bs-x1bs-y1-global-memory-matrix-by-bs-xbs-y-threads.

您面临以下问题:每个线程块的大小TILE_WIDTHxTILE_WIDTH应该填充大小的共享内存区域(TILE_WIDTH + Mask_width - 1)x(TILE_WIDTH + Mask_width - 1).

4)一般来说,有两个载荷的直观解释是什么?

由于共享内存区域(TILE_WIDTH + Mask_width - 1)x(TILE_WIDTH + Mask_width - 1)大于块大小TILE_WIDTHxTILE_WIDTH并假设它小于2xTILE_WIDTHxTILE_WIDTH,那么每个线程最多应将两个元素从全局内存移动到共享内存。这就是为什么要进行两阶段加载的原因。

1) The destY and destX指数。将输出索引除以输入图块宽度意味着什么?

这涉及指定加载的第一个加载阶段TILE_WIDTHxTILE_WIDTH来自全局内存的元素并填充共享内存区域的最上部。

所以,操作

dest = threadIdx.y * TILE_WIDTH + threadIdx.x;

展平通用线程的 2D 坐标,同时

destX = dest % w;
destY = dest / w; 

进行逆操作,因为它计算通用线程相对于共享内存区域的 2D 坐标。

2) The srcY add srcX指数。为什么destY and destX指数参与srcY add srcX index?

srcY = blockIdx.y * TILE_WIDTH + destY - Mask_radius;

srcX = blockIdx.x * TILE_WIDTH + destX - Mask_radius;

(blockIdx.x * TILE_WIDTH, blockIdx.y * TILE_WIDTH)如果块大小和共享内存大小相同,则为全局内存位置的坐标。由于您还从相邻图块“借用”内存值,因此您必须将上述坐标移动(destX - Mask_radius, destY - Mask_radius).

3)为什么在第二次加载时我们使用偏移量TILE_WIDTH * TILE_WIDTH?

你有这个偏移量是因为在第一个记忆阶段你已经填满了“第一个”TILE_WIDTHxTILE_WIDTH共享内存的位置。

EDIT

下图说明了压扁螺纹索引之间的对应关系dest和共享内存位置。在图中,蓝色框代表通用图块的元素,而红色框代表相邻图块的元素。蓝色和红色框的并集对应于整体共享内存位置。如您所见,所有256线程块的线程参与填充绿线上方共享内存的上部部分,而只有145参与填充绿线以下共享内存的下部。现在你也应该明白了TILE_WIDTH x TILE_WIDTH offset.

请注意,您最多有2由于参数的特定选择,每个线程的内存负载。例如,如果您有TILE_WIDTH = 8,那么线程块中的线程数为64,而共享内存大小为12x12=144,这意味着每个线程负责执行at least 2共享内存写入144/64=2.25.

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

将数据上传到共享内存中用于卷积核 的相关文章

  • 在 python docker 镜像上使用 GPU

    我正在使用一个python 3 7 4 slim busterdocker 镜像 我无法更改它 我想知道如何使用我的英伟达 GPU on it 我通常用一个tensorflow tensorflow 1 14 0 gpu py3并用一个简单
  • Golang调用CUDA库

    我正在尝试从 Go 代码中调用 CUDA 函数 我有以下三个文件 test h int test add void test cu global void add int a int b int c c a b int test add v
  • 为什么 gcc 和 NVCC (g++) 会看到两种不同的结构大小?

    我正在尝试将 CUDA 添加到 90 年代末编写的现有单线程 C 程序中 为此 我需要混合两种语言 C 和 C nvcc 是 c 编译器 问题在于 C 编译器将结构视为特定大小 而 C 编译器将相同的结构视为略有不同的大小 那很糟 我对此感
  • OpenCV GPU Farneback 光流在多线程中表现不佳

    我的应用程序使用 Opencv GPU 类gpu FarnebackOpticalFlow计算输入视频的一对连续帧之间的光流 为了加速该过程 我利用 OpenCV 的 TBB 支持在多线程中运行该方法 然而 多线程性能并不像单线程那样 为了
  • 多个进程可以共享一个 CUDA 上下文吗?

    这个问题是 Jason R 的后续问题comment https stackoverflow com questions 29964392 multiple cuda contexts for one device any sense co
  • 如何在使用 GPU 支持编译的 macOS 上安装 Xgboost?

    我尝试在过去 3 天的 MacOS Mojave 10 14 6 上安装集成了 GPU 支持的 xgboost 但是没有成功 我尝试了两种方法 pip 安装 xgboost xgboost 安装在这里 并且在没有 GPU 选项的情况下成功运
  • 仅使用 CUDA 进行奇异值计算

    我正在尝试使用新的cusolverDnSgesvdCUDA 7 0 用于计算奇异值的例程 完整代码如下 include cuda runtime h include device launch parameters h include
  • 运行时 API 应用程序中的 cuda 上下文创建和资源关联

    我想了解如何在 cuda 运行时 API 应用程序中创建 cuda 上下文并与内核关联 我知道这是由驱动程序 API 在幕后完成的 但我想了解一下创作的时间线 首先 我知道 cudaRegisterFatBinary 是第一个 cuda a
  • CUDA Visual Studio 2010 Express 构建错误

    我正在尝试在 64 位 Windows 7 上使用 Visual Studio 2010 Express 在 Windows 上开始 CUDA 编程 我花了一段时间来设置环境 然后我刚刚编写了我的第一个程序 helloWorld cu 目前
  • 无法在 CUDA 中执行设备内核

    我正在尝试在全局内核中调用设备内核 我的全局内核是矩阵乘法 我的设备内核正在查找乘积矩阵每列中的最大值和索引 以下是代码 device void MaxFunction float Pd float max int x threadIdx
  • NvCplGetThermalSettings 返回 false

    问题 您好 我正在尝试使用 Delphi 获取 nividia gtx 980 的 GPU 温度 我看过C 问题 他的解决方案是不使用nvcpl dll 我认为这不是正确的解决方案 因为 nivida 有完整的文档说明如何处理 API 见下
  • 加速Cuda程序

    要更改哪一部分来加速此代码 代码到底在做什么 global void mat Matrix a Matrix b int tempData new int 2 tempData 0 threadIdx x tempData 1 blockI
  • iOS 上的 OpenCV - GPU 使用情况?

    我正在尝试开发一个 iOS 应用程序 可以对来自相机的视频执行实时效果 就像 iPad 上的 Photobooth 一样 我熟悉 OpenCV 的 API 但如果大多数处理是在 CPU 上完成而不是在 GPU 上完成 我担心 iOS 上的性
  • Cuda 6.5 找不到 - libGLU。 (在 ubuntu 14.04 64 位上)

    我已经在我的ubuntu上安装了cuda 6 5 我的显卡是 GTX titan 当我想要制作 cuda 样本之一时 模拟 粒子 我收到这条消息 gt gt gt WARNING libGLU so not found refer to C
  • cuda中有模板化的数学函数吗? [复制]

    这个问题在这里已经有答案了 我一直在寻找 cuda 中的模板化数学函数 但似乎找不到 在普通的 C 中 如果我调用std sqrt它是模板化的 并且将根据参数是浮点数还是双精度数执行不同的版本 我想要这样的 CUDA 设备代码 我的内核将真
  • CUDA 矩阵加法时序,按行与按行比较按栏目

    我目前正在学习 CUDA 并正在做一些练习 其中之一是实现以 3 种不同方式添加矩阵的内核 每个元素 1 个线程 每行 1 个线程和每列 1 个线程 矩阵是方阵 并被实现为一维向量 我只需用以下命令对其进行索引 A N row col 直觉
  • 有没有一种有效的方法来优化我的序列化代码?

    这个问题缺乏细节 因此 我决定创建另一个问题而不是编辑这个问题 新问题在这里 我可以并行化我的代码吗 还是不值得 https stackoverflow com questions 17937438 can i parallelize my
  • 错误:NVIDIA-SMI 失败,因为无法与 NVIDIA 驱动程序通信

    NVIDIA SMI 抛出此错误 NVIDIA SMI 失败 因为无法与 NVIDIA 通信 司机 确保安装了最新的 NVIDIA 驱动程序并且 跑步 我清除了 NVIDIA 并按照提到的步骤重新安装了它here https askubun
  • 如何使用 CUDA/Thrust 对两个数组/向量根据其中一个数组中的值进行排序

    这是一个关于编程的概念问题 总而言之 我有两个数组 向量 我需要对一个数组 向量进行排序 并将更改传播到另一个数组 向量中 这样 如果我对 arrayOne 进行排序 则对于排序中的每个交换 arrayTwo 也会发生同样的情况 现在 我知
  • 如何读取 GPU 负载?

    我正在编写一个程序 用于监控计算机的各种资源 例如CPU使用率等 我还想监控 GPU 使用情况 GPU 负载 而不是温度 using System using System Collections Generic using System

随机推荐

  • 如何使用 astyle 在 C++ 方法中格式化左大括号?

    将函数的左大括号移动到下一行是一种常见的做法 如何使用astyle 代码美化器 在类方法中应用它 example this is an initial C code class Class public static int foo boo
  • 基于iOS的OpenGL ES编程

    我需要找到学习 iPhone 版 openGL ES 的资源 我已经看过 Brad Larson 的精彩视频 现在正在从苹果下载高级视频 我对 iOS 编程了解很多 但对 OpenGL 一无所知 因此资源不假设我已经了解 openGL 我想
  • 我可以将 moq 的 InSequence() 与 MockBehavior.Loose 一起使用吗?

    我试图执行后续调用验证 我发现 moq 支持 InSequence 方法 例如 MockSequence s new MockSequence validator InSequence s Setup m gt m IsValid It I
  • 如何在shiny中触发数据刷新?

    我有一个闪亮的应用程序 它将数据从 SQL 查询到数据帧中 然后从我的闪亮服务器 块中引用这些数据帧 到目前为止 我只在 RStudio 中运行它 因此每当我需要新数据时 我只需重新启动应用程序 然后在服务器加载之前它将获取所有新数据 我想
  • TIFFReadDirectory 使用 QPixmap::load( ) 读取 GeoTiff 时出现警告

    我有一个 geotiff 文件 我正在使用 QPixmap load 将其加载到 QPixmap 中 我多次在控制台上打印以下警告 但是 直接使用 libtiff 打开它不会出现警告 关于如何减轻 QT 中这些难看的警告有什么想法吗 TIF
  • Web应用程序在azure中出现http 404错误,但在本地运行

    我正在尝试创建一个连接到我的 Azure SQL 数据库并从数据中读取的 Web api 我使用了 VS19 中的 API 模板并添加了我自己的文件 我在本地运行了该应用程序 模板天气预报工作正常 并且我使用邮递员测试了我的 API 然后
  • CRAN 关于全局变量使用的政策

    在CRAN存储库策略文档中 明确指出 包不应修改全局环境 用户的工作空间 当我跑步时 R CMD check via devtools check 它只是声明 全局变量 x 没有可见的绑定 作为注释而不是警告 CRAN 不会接受用户提供的包
  • Visual Studio 容器工具要求在构建、调试或运行容器化项目之前运行 Docker

    我正在研究 Net core 微服务 我安装了包含 docker cli 和 kitematics 的 Docker Toolbox 之后 我在 Visual Studio 2017 中创建了一个简单的 Net Core Web api 项
  • 在 Ruby 中解析街道地址

    我正在将地址处理为数据库各自的字段格式 我可以得到门牌号和街道类型 但试图确定获得没有号码和最后一句话的街道的最佳方法 收到的标准街道地址为 res address 7707 Foo Bar Blvd 到目前为止我可以解析以下内容 hous
  • android中的activity作为对话框

    我想用一个activity as dialog我把活动的主题定为对话 我成功了 但 我遇到的问题是当我在活动之外单击时 它会自动关闭并且之前的活动开始 我尝试了一种方法来制作透明的父布局 它看起来不像对话框 我想使用此活动在我的应用程序中创
  • 通过客户端函数在服务器端调用非静态方法

    我可以通过使用服务器端的静态接收回调结果方法从服务器端获取对象 但我想在我的页面中运行一个非静态方法 通过调用客户端函数来填充 ajax 手风琴 我从服务器端调用的对象是一个复杂的对象 如果我通过回调结果获取它 则无法在客户端使用它 是否有
  • 如何启用 InstallShield 限量版 2015

    我想部署我的项目 为此我转到文件 gt 新项目 gt 其他项目类型 gt 设置和部署 但在那里我找不到任何选项 安装项目 我已经下载了InstallShield Limited Edition 但仍然出现相同的网页 要求我下载 Instal
  • javascript二叉搜索树实现[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有人知道用 Javascript 实现简单 BTree 的任何好例子吗 我有一堆随机到达的 东西 并且
  • 尝试在 openpyxl 中保存工作簿时,卡在 AttributeError: 'int' 对象没有属性 'reindex' 上

    我无法弄清楚这一点 它抱怨 wb save 行 在我的头撞到这个之后 我不知道是什么原因造成的 我怀疑这与尝试打开一张空白纸并在进行格式化操作后保存它有关 但我无法想象我在那里所做的事情导致了这个问题 当我打开现有的电子表格并进行操作时 它
  • 以编程方式在给定时间暂停/停止 Android MediaPlayer

    我研究了一下 但找不到解决这个问题的任何方法 我想玩一个MediaPlayer并在给定时间暂停 停止 即 从第 6 秒播放到第 17 秒 我知道我可以设置它的起点seekTo 方法 但我可以通过设置终点来暂停 停止播放 当然 在达到文件结束
  • 读取文件列表,应用函数并用相同名称重写

    我有一组包含重复条目的 csv 文件 我需要删除并重写具有相同名称和格式的文件 这是我到目前为止所做的 filenames lt list files pattern csv datalist lt lapply filenames fun
  • 如何在 IIS 中监视 .NET MySQL 数据连接器的连接池

    我已经在谷歌上搜索了相当多的信息 但无法找到确切的答案 我们在日志中看到以下错误 超时已过 获取之前已过了超时时间 来自池的连接 发生这种情况的原因可能是所有 连接正在使用中并且已达到最大池大小 堆栈跟踪 位于 MySql Data MyS
  • MXE - 使用 cmake 和 mingw 交叉编译时对 Qt 的未定义引用

    我正在尝试编译电子通桌面 https github com electronpass electronpass desktop 对于 Windows 使用MXE http mxe cc在Linux上 我已经成功编译了它的所有依赖项 包括li
  • 使用表的字段值重命名 SQL 表的列

    我正在尝试执行一个 SQL 查询 该查询将使用表中第一个记录集中的文本重命名表的列 我的桌子看起来像这样 COL1 COL2 COL3 COL4 COL5 COL6 REASON ITEMDATE ITEMTIME SITENAME EVE
  • 将数据上传到共享内存中用于卷积核

    我在理解评论中提到的批量加载时遇到一些困难 为了计算像素中的卷积 大小为 5 的掩模必须以该特定像素为中心 图像被分成图块 应用卷积掩模后的这些图块是最终输出图块 其大小为TILE WIDTH TILE WIDTH 对于属于输出图块边界的像