__global__ 函数如何像 C/C++ 那样返回值或中断

2023-11-23

最近我一直在 CUDA 上进行字符串比较工作,我想知道 __global__ 函数在找到我正在寻找的确切字符串时如何返回一个值。

我的意思是,我需要包含大量线程的 __global__ 函数来同时在一个大字符串池中查找某个字符串,并且我希望一旦捕获到确切的字符串, __global__ 函数就可以停止所有线程并返回回到主函数,并告诉我“他做到了”!

我正在使用 CUDA C。我怎样才能实现这一目标?


在 CUDA(或 NVIDIA GPU)中,一个线程无法中断所有正在运行的线程的执行。你不能在发现结果后立即退出内核,这在今天是不可能的。

但你可以让所有线程退出尽快地当一个线程找到结果后。这是一个如何做到这一点的模型。

__global___ void kernel(volatile bool *found, ...) 
{
    while (!(*found) && workLeftToDo()) {

       bool iFoundIt = do_some_work(...); // see notes below

       if (iFoundIt) *found = true;
    }
}

关于此的一些注释。

  1. 注意使用volatile。这个很重要。
  2. 确保初始化found— 必须是一个设备指针 — 到false在启动内核之前!
  3. 当另一个线程更新时,线程不会立即退出found。仅当它们下次返回到 while 循环顶部时才会退出。
  4. 你如何实施do_some_work很重要。如果工作量太大(或变化太大),那么找到结果后退出的延迟将会很长(或变化)。如果工作量太少,那么您的线程将花费大部分时间进行检查found而不是做有用的工作。
  5. do_some_work还负责分配任务(即计算/递增索引),以及如何做到这一点是特定于问题的。
  6. 如果您启动的块数远大于当前 GPU 上内核的最大占用率,并且在第一个运行的线程块“波”中未找到匹配项,则该内核(以及下面的内核)可能会死锁。如果在第一波中找到匹配项,则后面的块将仅在之后运行found == true,这意味着它们将启动,然后立即退出。解决方案是仅启动可同时驻留的尽可能多的块(也称为“最大启动”),并相应地更新任务分配。
  7. 如果任务数量比较少,可以更换whileif并运行足够的线程来覆盖任务数量。这样就不会出现死锁(但上一点的第一部分适用)。
  8. workLeftToDo()是特定于问题的,但是当没有剩余工作要做时它会返回 false,这样我们就不会在这种情况下陷入僵局未找到匹配项.

现在,上述情况可能会导致过度的分区露营(所有线程都在同一内存上运行),特别是在没有 L1 缓存的旧架构上。因此,您可能想要编写一个稍微复杂的版本,使用每个块的共享状态。

__global___ void kernel(volatile bool *found, ...) 
{
    volatile __shared__ bool someoneFoundIt;

    // initialize shared status
    if (threadIdx.x == 0) someoneFoundIt = *found;
    __syncthreads();

    while(!someoneFoundIt && workLeftToDo()) {

       bool iFoundIt = do_some_work(...); 

       // if I found it, tell everyone they can exit
       if (iFoundIt) { someoneFoundIt = true; *found = true; }

       // if someone in another block found it, tell 
       // everyone in my block they can exit
       if (threadIdx.x == 0 && *found) someoneFoundIt = true;

       __syncthreads();
    }
}

这样,每个块有一个线程轮询全局变量,并且只有找到匹配的线程才会写入它,因此全局内存流量被最小化。

另外: __global__ 函数是无效的,因为很难定义如何将数千个线程的值返回到单个 CPU 线程中。对于用户来说,在设备或零拷贝内存中设计一个适合其目的的返回数组很简单,但很难建立通用机制。

免责声明:在浏览器中编写的代码,未经测试,未经验证。

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

__global__ 函数如何像 C/C++ 那样返回值或中断 的相关文章

  • 从 CUDA 设备写入输出文件

    我是 CUDA 编程的新手 正在将 C 代码重写为并行 CUDA 新代码 有没有一种方法可以直接从设备写入输出数据文件 而无需将数组从设备复制到主机 我假设如果cuPrintf存在 一定有地方可以写一个cuFprintf 抱歉 如果答案已经
  • 如何为 CUDA 内核选择网格和块尺寸?

    这是一个关于如何确定CUDA网格 块和线程大小的问题 这是对已发布问题的附加问题here https stackoverflow com a 5643838 1292251 通过此链接 talonmies 的答案包含一个代码片段 见下文 我
  • 内联 PTX 汇编代码强大吗?

    我看到一些代码示例 人们在 C 代码中使用内联 PTX 汇编代码 CUDA工具包中的文档提到PTX很强大 为什么会这样呢 如果我们在 C 代码中使用这样的代码 我们会得到什么好处 内联 PTX 使您可以访问未通过 CUDA 内在函数公开的指
  • 最小化 MC 模拟期间存储的 cuRAND 状态数量

    我目前正在 CUDA 中编写蒙特卡罗模拟 因此 我需要生成lots使用随机数cuRAND图书馆 每个线程处理一个巨大的元素floatarray 示例中省略 并在每次内核调用时生成 1 或 2 个随机数 通常的方法 参见下面的示例 似乎是为每
  • CUDA 5.0错误LNK2001:cuda方法无法解析的外部符号

    我的链接器有错误 1 gt ManifestResourceCompile 1 gt All outputs are up to date 1 gt kernel cu obj error LNK2001 unresolved extern
  • CUDA NSight 未随 Windows 8 上的 CUDA 5.0 安装文件一起安装? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 据我所知 Nvidia 网站上没有 Nsight Eclipse 的下载链接 它说它将由 CUDA 5 安装本机安装 但并没有随CUDA安装一起安装
  • Bank 在字长方面存在冲突

    我读过一些关于共享内存的好文章 但我对银行冲突有初步疑问 据说 如果线程 1 和线程 2 从存储体 0 访问字 0 则不存在存储体冲突 但如果他们访问不同的单词 就会出现银行冲突 但我的问题是不同的单词如何可以驻留在一个银行中 由于bank
  • CUDA计算能力2.0。全局内存访问模式

    CUDA 计算能力 2 0 Fermi 全局内存访问通过 768 KB L2 缓存进行 看起来 开发人员不再关心全局内存库 但全局内存仍然非常慢 因此正确的访问模式很重要 现在的重点是尽可能多地使用 重用 L2 我的问题是 如何 我将感谢一
  • OpenCV 2.4.3rc 和 CUDA 4.2:“OpenCV 错误:没有 GPU 支持”

    我在这张专辑中上传了几张截图 https i stack imgur com TELST jpg https i stack imgur com TELST jpg 我正在尝试在 Visual Studio 2008 中的 OpenCV 中
  • GPU上动态分配内存

    是否可以在内核内的 GPU 全局内存上动态分配内存 我不知道我的答案有多大 因此我需要一种方法为答案的每个部分分配内存 CUDA 4 0 允许我们使用 RAM 这是一个好主意还是会降低速度 可以在内核中使用 malloc 检查以下内容 摘自
  • 将内核链接到 PTX 函数

    我可以使用 PTX 文件中包含的 PTX 函数作为外部设备函数 将其链接到另一个应调用该函数的 cu 文件吗 这是另一个问题CUDA 将内核链接在一起 https stackoverflow com questions 20636800 c
  • 在 Cuda 中简单添加两个 int,结果始终相同

    我开始了学习Cuda的旅程 我正在玩一些 hello world 类型的 cuda 代码 但它不起作用 我不知道为什么 代码非常简单 取两个整数并将它们添加到 GPU 上并返回结果 但无论我将数字更改为什么 我都会得到相同的结果 如果数学那
  • 使用推力来处理 CUDA 类中的向量?

    我对 C 类的推力的适用性有疑问 我正在尝试实现一个类对象 该对象接收顶点的 x y z 坐标作为 ver1 ver2 和 ver3 然后 分配给一个三角形并计算面积和法向量 然而 我不太明白如何创建一类推力向量 这是我从文件中读取的顶点坐
  • 完全禁用 NVCC 优化

    我正在尝试测量 GPU 上的峰值单精度触发器 为此我正在修改 PTX 文件以在寄存器上执行连续的 MAD 指令 不幸的是 编译器正在删除所有代码 因为它实际上没有做任何有用的事情 因为我没有执行任何数据的加载 存储 是否有编译器标志或编译指
  • 如何从C++头文件调用CUDA文件?

    我知道从 c 文件调用 cu 文件的方法 但现在我想从 C 头文件调用 cu 文件 有可能做到吗 如果是这样 我应该如何设置我的项目 请帮忙 这是一个有效的例子 file1 h int hello file2 h include
  • 为什么 CUDA 内存复制速度会这样,有一些恒定的驱动程序开销?

    在我的旧 GeForce 8800GT 上使用 CUDA 内存时 我总是会遇到奇怪的 0 04 毫秒开销 我需要将 1 2K 传输到设备的常量内存中 处理其中的数据并从设备中仅获取一个浮点值 我有一个使用 GPU 计算的典型代码 alloc
  • 如何使用 Visual Studio 2008 调试 CUDA 内核代码?

    嘿 我正在使用带有 CUDA 3 2 的 Visual Studio 2008 我正在尝试调试具有此签名的函数 MatrixMultiplication Kernel lt lt
  • Simpson 的 Thrust 集成代码在两台使用 NVC++ 的机器上输出不同的结果

    我写了一个数值积分代码 include
  • 在 CUDA 内核中使用虚拟函数

    所以我想在设备上分配一个具有虚拟函数的对象 然后调用内核并执行其中一些虚拟函数 我尝试了两种方法来做到这一点 但都不起作用 1 使用 cudaMalloc 和 cudaMemcpy 从主机分配和复制对象 这会复制包含主机内存指针的虚拟函数表
  • 如何在 Java 编程中使用 GPU

    我这些天都在使用 CUDAC 来访问 GPU 但现在我的导游要求我使用 Java 和 GPU 于是我在网上搜索发现Rootbeer是最好的选择 但我无法理解如何使用 Rootbeer 运行程序 可以有一个吗告诉我使用 Rootbeer 的步

随机推荐