在内核 OpenCL 中实现 FIFO 的最佳方法

2024-05-02

目标:在 OpenCL 中实现下图所示。 OpenCl 内核所需的主要内容是将系数数组和临时数组相乘,然后最后将所有这些值累加为 1。 (这可能是最耗时的操作,并行性在这里非常有帮助)。

我正在为内核使用一个辅助函数来执行乘法和加法(我希望这个函数也将是并行的)。

图片说明:

一次一个,值被传递到与系数数组大小相同的数组(临时数组)中。现在每次将单个值传递到该数组中,临时数组与系数数组并行相乘,然后将每个索引的值连接到一个元素中。这将继续,直到输入数组到达其最终元素。

我的代码会发生什么情况?

对于输入中的 60 个元素,需要超过 8000 毫秒!我总共有 120 万个输入需要传入。我知道有一个更好的解决方案可以完成我正在尝试的事情。下面是我的代码。

以下是我所知道的代码中肯定存在的一些问题。当我尝试将系数值与临时数组相乘时,它崩溃了。这是因为 global_id。我想要这条线做的只是将两个数组并行相乘。

我试图找出为什么执行 FIFO 函数需要这么长时间,所以我开始注释行。我首先对除 FIFO 函数的第一个 for 循环之外的所有内容进行注释。结果这花了 50 毫秒。然后当我取消注释下一个循环时,它跳到了 8000 毫秒。因此,延迟可能与数据传输有关。

我可以在 OpenCl 中使用寄存器移位吗?也许对整数数组使用某种逻辑移位方法? (我知道有一个“>>”运算符)。

float constant temp[58];
float constant tempArrayForShift[58];
float constant multipliedResult[58];

float fifo(float inputValue, float *coefficients, int sizeOfCoeff) {

//take array of 58 elements (or same size as number of coefficients)
//shift all elements to the right one
//bring next element into index 0 from input
//multiply the coefficient array with the array thats the same size of coefficients and accumilate
//store into one output value of the output array
//repeat till input array has reached the end

int globalId = get_global_id(0); 

float output = 0.0f;

//Shift everything down from 1 to 57
//takes about 50ms here
for(int i=1; i<58; i++){
    tempArrayForShift[i] = temp[i];
}

//Input the new value passed from main kernel. Rest of values were shifted over so element is written at index 0.
tempArrayForShift[0] = inputValue;
//Takes about 8000ms with this loop included
//Write values back into temp array
for(int i=0; i<58; i++){
    temp[i] = tempArrayForShift[i];
}

//all 58 elements of the coefficient array and temp array are multiplied at the same time and stored in a new array
//I am 100% sure this line is crashing the program.
//multipliedResult[globalId] = coefficients[globalId] * temp[globalId];

//Sum the temp array with each other. Temp array consists of coefficients*fifo buffer
for (int i = 0; i <  58; i ++) {
//  output = multipliedResult[i] + output;
}

//Returned summed value of temp array
return output;
}


__kernel void lowpass(__global float *Array, __global float *coefficients, __global float *Output) { 

//Initialize the temporary array values to 0
for (int i = 0; i <  58; i ++) {
    temp[i] = 0;
    tempArrayForShift[i] = 0;
    multipliedResult[i] = 0;
}

//fifo adds one element in and calls the fifo function. ALL I NEED TO DO IS SEND ONE VALUE AT A TIME HERE.
for (int i = 0; i <  60; i ++) {
    Output[i] = fifo(Array[i], coefficients, 58);
}

}

我在 OpenCl 上遇到这个问题已经很长时间了。我不确定如何一起实现并行指令和顺序指令。

我正在考虑的另一种选择

在主 cpp 文件中,我正在考虑在那里实现 fifo 缓冲区并让内核执行乘法和加法。但这意味着我必须在循环中调用内核 1000 多次。这是更好的解决方案吗?或者它只是完全低效。


为了充分利用 GPU 的性能,您需要将工作并行化到多个线程。在您的代码中,您仅使用单个线程,而 GPU 每个线程的速度非常慢,但如果同时运行多个线程,则速度可能会非常快。在这种情况下,您可以对每个输出值使用单个线程。您实际上不需要通过数组移动值:对于每个输出值,都会考虑包含 58 个值的窗口,您只需从内存中获取这些值,将它们与系数相乘,然后写回结果即可。

一个简单的实现是(使用与输出值一样多的线程启动):

__kernel void lowpass(__global float *Array, __global float *coefficients, __global float *Output) 
{ 
    int globalId = get_global_id(0); 
    float sum=0.0f;
    for (int i=0; i< 58; i++)
    {
        float tmp=0;
        if (globalId+i > 56)
        {
            tmp=Array[i+globalId-57]*coefficient[57-i];
        }
        sum += tmp;
    }
    output[globalId]=sum;
}

这并不完美,因为它生成的内存访问模式对于 GPU 来说并不是最佳的。缓存可能会有所帮助,但显然还有很大的优化空间,因为这些值会被重复使用多次。您尝试执行的操作称为卷积(1D)。 NVidia 在其 GPU 计算 SDK 中有一个名为 oclConvolutionSeparable 的 2D 示例,该示例显示了优化版本。您可以使用其 convolutionRows 内核进行 1D 卷积。

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

在内核 OpenCL 中实现 FIFO 的最佳方法 的相关文章

随机推荐

  • 如何确定哪个 URL 被 App Transport Security 阻止?

    我正在将 iOS 应用程序升级到 iOS 9 并且有一些不安全的 URL 并且我需要应用程序传输安全性的一些例外情况 我已经添加了我所知道的两个 但现在出现了一些警告 应用程序传输安全性已阻止明文 HTTP http 资源加载 因为它不安全
  • 使用php.ini、.htaccess和zlib.output压缩js、css和php文件

    我一直在尝试使用 gzip 压缩我的网站 尽管我的服务器不允许我使用 mod deflate 所以我在这里找到了替代解决方案 http www warpconduit net 2010 10 23 enabling gzip compres
  • 使用 JavaScript 更改 iframe 中的 URL

    我有一个 iframe 它从父页面调用一个函数 该函数是 window location 但这不会更改 url 有没有办法让 iframe 从父页面调用函数 这会导致 iframe 更改 url 我还有一个基本问题 如果我有一个 ifram
  • 传单:同一页上有多个地图

    我搜索过类似的问题 但没有找到适合我的情况的答案 我想使用 3 张传单地图 每张都有不同的内容 出现两个问题 仅显示第一个 比例和缩放控件仅显示在第三个中 我附上了一个 jsfiddle 以防你能帮忙 const mapbox L tile
  • C++11 左值到右值的转换?

    我认为我缺少一些关于左值到右值标准转换的基本知识 从 C 11 4 1 开始 非函数 非数组类型 T 的左值可以转换为纯右值 所以我们声明一个变量x int x 42 一种表达x在此范围内现在是左值 因此也是左值 它满足 4 1 中左值到右
  • HTTP PUT 请求通常如何发出?

    我知道 HTTP PUT 是一个幂等请求 根据定义 引用自rfc http www w3 org Protocols rfc2616 rfc2616 sec9 html The PUT method requests that the en
  • 实例标准化与批量标准化

    据我所知 批量归一化通过将激活转向单位高斯分布来帮助加快训练速度 从而解决梯度消失问题 批量归一化行为在训练 使用每个批次的平均值 var 和测试时间 使用训练阶段的最终运行平均值 var 时应用不同 另一方面 实例归一化充当本文提到的对比
  • 删除添加到购物车通知并更改 Woocommerce 中的“添加到购物车”按钮

    How to remove has been added to your cart text from shopping cart page and how to replace quantity and add to cart butto
  • PHP - 停止显示错误中的完整路径

    有什么方法可以告诉 PHP 不显示错误 警告或通知消息中存在任何错误的文件的完整路径 我知道我可以禁用错误 但是 只是为了避免任何风险 例如 我的脚本返回一个错误 显示如下 Fatal error Call to undefined fun
  • 从 ARM 模板创建 Azure Web 应用程序槽,无需复制原始 Web 应用程序配置

    我正在尝试通过 ARM 模板创建 Web 应用程序插槽 我能够创建它们 但看起来默认行为是将它们创建为当前 Web 应用程序状态的副本 这导致我的插槽继承应用程序设置 连接字符串 虚拟目录 这是演示行为的复制示例https github c
  • Eclipse、Subclipse 1.8.2、SVN 1.7.0 每次操作都要求输入密码

    我安装新的后日食靛蓝 它会要求我输入密码SVN存储库透视图 例如 浏览每个文件夹并再次询问密码 正常使用SVNKit 它要求输入密码每次会话一次 SVNKit 不支持SVN 1 7 0 yet 我该如何解决这个问题 或者这是 JavaHL
  • C#:选择属性包含子字符串的节点的 XPath?

    我可以使用XPath选择代码包含UK的国家节点吗
  • 文件上传控件仅上传PDF

    我有一个像这样的文件控件 div class form group Html LabelFor m gt m File new class col md 2 control label div class col md 10 Html Te
  • 如何使用 Android 1.5 录制音频?

    如何使用 Android 录制一些音频 package com benmccann android hello import java io File import java io IOException import android me
  • PDO 和 IS NOT NULL 函数

    我是 PDO 新手 我想知道是否有相当于 mysql 语句的语句来检查参数是否不为空 例如 SELECT FROM table WHERE param IS NOT NULL 我试过这个 pdo gt prepare SELECT FROM
  • Javascript:除了“use strict”之外,还有哪些其他“use”指令?

    Besides use strict 还有哪一个use有指令吗 指令序言 JavaScript 引擎可能使用的部分 中还有一些示例 use strict use asm 莫斯拉的asm js http asmjs org 是该语言的一个子集
  • 存储应用程序配置设置

    在 AngularJS 中存储应用程序配置设置的最佳位置是什么 这可能是应用程序常量 查找等 可以从控制器和服务或工厂使用 我可以创建一个单独的服务来存储和检索这些东西 但我想知道是否有另一个合适的地方来存储和检索这些东西 您可以使用持续的
  • 如何检测 iPhone 中按下的键盘按键?

    我想检测用户何时按下任何键盘键 仅在键入任何字符时调用的任何方法 而不是在显示键盘时调用的方法 Thanks 您可以在用户每次按键时直接处理键盘事件 Swift 对于文本字段 请使用以下委托方法 func textField textFie
  • 为什么我的 Visual Studio .obj 文件比输出的 .exe 文件大?

    作为背景 我是一个开源项目的开发人员 一个名为开放框架 http www openframeworks cc 这是不同库的包装器 例如 opengl quicktime freeImage 等 在下一个版本中 我们添加了一个名为 POCO
  • 在内核 OpenCL 中实现 FIFO 的最佳方法

    目标 在 OpenCL 中实现下图所示 OpenCl 内核所需的主要内容是将系数数组和临时数组相乘 然后最后将所有这些值累加为 1 这可能是最耗时的操作 并行性在这里非常有帮助 我正在为内核使用一个辅助函数来执行乘法和加法 我希望这个函数也