问题标签 [gpgpu]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
cuda - 如何优化 cuda 程序以获得更好的性能?
我为生成密钥编写了 matlab 程序(cuda)。
如何优化 cuda 程序以获得更好的性能?
opencl - 在 GPU 上计算最简单的函数是什么?
我刚开始学习 OpenCL。我试图了解将函数/算法移动到 GPU 时预期的性能提升。
大多数教程中给出的最基本的内核是一个内核,它接受两个数字数组并将相应索引处的值相加并将它们添加到第三个数组中,如下所示:
我假设您永远无法证明在 GPU 上计算它是合理的,内存传输的权重会超过在 CPU 上计算它所需的时间(我可能对此错了,因此这个问题)。
我想知道的是,在使用 OpenCL 内核而不是 CPU 时,您期望显着加速的最简单的例子是什么?
rgb - GPU YUV 转 RGB。值得努力?
我必须将几个完整的 PAL 视频 (720x576@25) 从 YUV 4:2:2 实时转换为 RGB,并且可能对每个视频进行自定义调整大小。我已经考虑过使用 GPU,因为我已经看到了一些这样做的例子(除了它是 4:4:4,所以 bpp 在源和命运上是相同的)——http: //www.fourcc.org/源码/YUV420P-OpenGL-GLSLang.c
但是,我没有任何使用 GPU 的经验,我不确定可以做什么。据我了解,该示例只是将视频帧转换为 YUV 并将其显示在屏幕上。
是否有可能获得处理后的帧?将其发送到 GPU、对其进行转换并再次发送到主存是否值得付出努力,还是会降低性能?
有点特定于平台,假设我在 Windows 上工作,是否可以从窗口获取 OpenGL 或 DirectDraw 表面,以便 GPU 可以直接绘制到它?
java - Java 中 GPGPU/CUDA/OpenCL 的最佳方法?
图形处理单元 ( GPGPU )上的通用计算是一个非常有吸引力的概念,可以利用 GPU 的能力进行任何类型的计算。
我很想将 GPGPU 用于图像处理、粒子和快速几何运算。
目前,该领域的两个竞争者似乎是 CUDA 和 OpenCL。我想知道:
- OpenCL 是否可以在 Windows/Mac 上的 Java 中使用?
- 与 OpenCL/CUDA 接口的库方法是什么?
- 直接使用 JNA 是一种选择吗?
- 我是不是忘记了什么?
任何现实世界的经验/例子/战争故事都值得赞赏。
gpu - NVIDIA GPU 和 PhysX 引擎
NVIDIA PhysX 引擎是如何在 NVIDIA GPU 中实现的:它是协处理器还是物理算法被实现为在 GPU 管道中执行的片段程序?
algorithm - 最快的固定长度 6 int 数组
在回答另一个 Stack Overflow 问题(这个)时,我偶然发现了一个有趣的子问题。对 6 个整数的数组进行排序的最快方法是什么?
由于问题非常低级:
- 我们不能假设库是可用的(并且调用本身有它的成本),只有纯 C
- 为了避免清空指令管道(成本非常高),我们可能应该尽量减少分支、跳转和所有其他类型的控制流中断(比如隐藏在
&&
or中的序列点后面的那些||
)。 - 房间受到限制,最小化寄存器和内存使用是一个问题,理想情况下,就地排序可能是最好的。
实际上,这个问题是一种高尔夫,其目标不是最小化源长度而是最小化执行时间。我将其称为“Zening”代码,正如Michael Abrash所著的Zen of Code optimization及其续集的书名中所使用的那样。
至于为什么有趣,有好几层:
- 该示例简单易懂,易于测量,涉及的C技能不多
- 它显示了为问题选择好的算法的效果,以及编译器和底层硬件的效果。
这是我的参考(天真,未优化)实现和我的测试集。
原始结果
随着变体的数量越来越多,我将它们全部收集在一个可以在此处找到的测试套件中。感谢 Kevin Stock,实际使用的测试比上面显示的要简单一些。您可以在自己的环境中编译和执行它。我对不同目标架构/编译器的行为非常感兴趣。(好的,伙计们,把它放在答案中,我会为新结果集的每个贡献者 +1)。
一年前,我向 Daniel Stutzbach(打高尔夫球)给出了答案,因为他是当时最快解决方案(排序网络)的来源。
Linux 64 位、gcc 4.6.1 64 位、Intel Core 2 Duo E8400、-O2
- 直接调用 qsort 库函数:689.38
- 天真的实现(插入排序):285.70
- 插入排序 (Daniel Stutzbach) : 142.12
- 插入排序展开:125.47
- 排名顺序:102.26
- 寄存器排名顺序:58.03
- 排序网络 (Daniel Stutzbach):111.68
- 排序网络(Paul R):66.36
- 使用快速交换对网络 12 进行排序:58.86
- 排序网络 12 重新排序交换:53.74
- 排序网络 12 重新排序简单交换:31.54
- 带快速交换的重新排序的排序网络:31.54
- 带快速交换 V2 的重新排序的排序网络:33.63
- 内联冒泡排序(Paolo Bonzini):48.85
- 展开插入排序 (Paolo Bonzini) : 75.30
Linux 64 位、gcc 4.6.1 64 位、Intel Core 2 Duo E8400、-O1
- 直接调用 qsort 库函数:705.93
- 天真的实现(插入排序):135.60
- 插入排序 (Daniel Stutzbach) : 142.11
- 插入排序展开:126.75
- 排名顺序:46.42
- 寄存器排名顺序:43.58
- 排序网络 (Daniel Stutzbach):115.57
- 排序网络(Paul R):64.44
- 使用快速交换对网络 12 进行排序:61.98
- 排序网络 12 重新排序交换:54.67
- 排序网络 12 重新排序简单交换:31.54
- 带快速交换的重新排序的排序网络:31.24
- 带快速交换 V2 的重新排序的排序网络:33.07
- 内联冒泡排序(Paolo Bonzini):45.79
- 展开插入排序(Paolo Bonzini):80.15
我将 -O1 和 -O2 结果都包括在内,因为令人惊讶的是,对于几个程序来说,O2 的效率低于O1。我想知道什么具体的优化有这个效果?
对提议的解决方案的评论
插入排序 (Daniel Stutzbach)
正如预期的那样,最小化分支确实是一个好主意。
排序网络 (Daniel Stutzbach)
比插入排序好。我想知道主要效果是否不是来自避免外部循环。我通过展开插入排序进行了尝试,确实我们得到了大致相同的数字(代码在这里)。
排序网络 (Paul R)
迄今为止最好的。我用来测试的实际代码在这里。还不知道为什么它的速度几乎是其他排序网络实现的两倍。参数传递?快速最大值?
排序网络 12 带有快速交换的交换
正如 Daniel Stutzbach 所建议的,我将他的 12 交换排序网络与无分支快速交换相结合(代码在此处)。它确实更快,是迄今为止最好的,利润率很小(大约 5%),正如使用少掉 1 次交换所预期的那样。
有趣的是,无分支交换似乎比在 PPC 架构上使用 if 的简单交换效率低很多(4 倍)。
调用库 qsort
为了提供另一个参考点,我还按照建议尝试调用库 qsort(代码在此处)。正如预期的那样,它要慢得多:慢了 10 到 30 倍......随着新的测试套件变得很明显,主要问题似乎是第一次调用后库的初始加载,它与其他的相比并没有那么差版本。在我的 Linux 上,它只慢了 3 到 20 倍。在其他人用于测试的某些架构上,它似乎甚至更快(我对此感到非常惊讶,因为库 qsort 使用更复杂的 API)。
排序
Rex Kerr 提出了另一种完全不同的方法:对数组中的每一项直接计算其最终位置。这是有效的,因为计算排名顺序不需要分支。这种方法的缺点是它需要三倍于数组的内存量(一份数组和变量的副本来存储排名顺序)。性能结果非常令人惊讶(也很有趣)。在我的 32 位操作系统和 Intel Core2 Quad E8300 的参考架构上,循环计数略低于 1000(如使用分支交换对网络进行排序)。但是当在我的 64 位机器(Intel Core2 Duo)上编译和执行时,它的表现要好得多:它成为迄今为止最快的。我终于找到了真正的原因。我的 32 位盒子使用 gcc 4.4.1 和我的 64 位盒子 gcc 4.4。
更新:
正如上面公布的数字所示,这种效果仍然被更高版本的 gcc 增强,并且排名顺序始终是任何其他替代方案的两倍。
使用重新排序的交换对网络 12 进行排序
使用 gcc 4.4.3 的 Rex Kerr 提案的惊人效率让我想知道:内存使用量是 3 倍的程序怎么可能比无分支排序网络更快?我的假设是,它具有较少的读写依赖,从而可以更好地使用 x86 的超标量指令调度程序。这给了我一个想法:重新排序交换以最大程度地减少写入后读取的依赖关系。更简单地说:当您这样做时,SWAP(1, 2); SWAP(0, 2);
您必须等待第一次交换完成才能执行第二次交换,因为两者都访问公共存储单元。当你这样做时SWAP(1, 2); SWAP(4, 5);
,处理器可以并行执行。我试过了,它按预期工作,排序网络的运行速度快了大约 10%。
使用简单交换对网络进行排序 12
在最初的帖子 Steinar H. Gunderson 建议一年后,我们不应该试图超越编译器并保持交换代码简单。这确实是一个好主意,因为生成的代码快了大约 40%!他还提出了使用 x86 内联汇编代码手动优化的交换,仍然可以节省更多的周期。最令人惊讶的是(它说明了程序员的心理),一年前没有人尝试过那个版本的交换。我用来测试的代码在这里。其他人提出了编写 C 快速交换的其他方法,但它产生的性能与具有良好编译器的简单交换相同。
“最佳”代码现在如下:
如果我们相信我们的测试集(是的,它很差,它的唯一好处是简短、简单且易于理解我们正在测量的内容),那么生成的代码的平均循环数低于 40 个循环(执行 6 次测试)。这使得每次交换平均为 4 个周期。我称之为惊人的快。还有其他可能的改进吗?
opengl - GLSL着色器渲染到纹理不保存alpha值
更新:Danvil 在下面的评论中解决了这个问题。我的纹理格式是 GL_RGB 而不是 GL_RGBA 这当然意味着不保留 alpha 值。不知道为什么我没有意识到……谢谢丹维尔。
我正在使用 GLSL 着色器渲染到纹理,然后将该纹理作为输入发送到第二个着色器。对于第一个纹理,我使用 RGB 通道将颜色数据发送到第二个 GLSL 着色器,但我想使用 alpha 通道发送一个浮点数,第二个着色器将用作其程序的一部分。问题是当我在第二个着色器中读取纹理时,alpha 值始终为 1.0。我通过以下方式对此进行了测试:
在第一个着色器结束时,我这样做了:
然后在第二个纹理中,我使用沿线的东西读取第一个纹理的值
我的输出中没有像素是黑色的,而如果我将上面的代码更改为读取
在第二个着色器中
所有适当的像素都是黑色的。这意味着由于某种原因,当我在第一个着色器中将 alpha 值设置为 1.0 以外的值并渲染到纹理时,第二个着色器仍将其视为 1.0。
在渲染到纹理之前,我 glDisable(GL_BLEND);
对我来说似乎很清楚,问题与 OpenGL 以某种对我来说并不明显的方式处理 alpha 值有关,因为我可以按照我想要的方式使用蓝色通道,并且发现那里的人会立即看到问题.
此外,我调用着色器程序的方式是绘制一个四边形(我正在渲染到具有纹理的帧缓冲区):
cuda - GPGPU 上的金融应用
我想知道使用 GPGPU 可以实现什么样的金融应用程序。我知道使用 CUDA 在 GPGPU 上使用蒙特卡罗模拟的期权定价/股票价格估计。有人可以列举在金融领域的任何应用程序中使用 GPGPU 的各种可能性吗?
floating-point - CUDA中的双精度浮点
CUDA 是否支持双精度浮点数?
另外,同样的原因是什么?
cuda - 用于 GPU 编程的 DirectCompute 与 OpenCL?
我有一些(财务)任务应该很好地映射到 GPU 计算,但我不确定我应该使用 OpenCL 还是 DirectCompute。我做了一些 GPU 计算,但那是很久以前(3 年)。我是通过 OpenGL 完成的,因为当时没有任何替代方案。
我看过一些 OpenCL 演示,它看起来非常好。我还没有看到有关 DirectCompute 的任何信息,但我希望它也很好。
目前我对跨平台兼容性不感兴趣,此外,我希望这两个模型足够相似,不会在尝试从一个模型转换到另一个模型时引起大麻烦。
那么,你用过这两个中的任何一个吗?特别是 DirectCompute?它与 OpenCL(和 CUDA)相比如何?