草庐IT

c++ - float 组的更快 abs-max

coder 2023-11-15 原文

我需要实时绘制音频的峰值表。每秒最少 44100 个样本乘以最少 40 个流。每个缓冲区包含 64 到 1024 个样本。我需要从每个缓冲区中获取 abs max。 (然后这些通过一种低通滤波器馈送并以大约 20 毫秒的间隔绘制。)

for(int i = 0; i < numSamples; i++)
{ 
      absMaxOfBuffer = MAX( fabs( buffer[i] ), absMaxOfBuffer);
}

我现在就是这样做的。我想做得更快。缓冲器在 -1 到 1 范围内 float ,因此是晶圆厂。

问题,是否有一些棘手的 comp-sci quicksort-esque 方法可以更快地完成此操作?

否则, float 的无分支 ABS 和 MAX 函数是否存在?

编辑: 主要平台是 Linux/gcc,但计划了一个 Windows 端口(可能与 mingw 一起)。

编辑,第二个:
我接受了 onebyone 因为关于实际算法结构的一点是问题的核心。
我会尝试将循环展开到四次,将符号位归零,然后使用 SSE(maxps 指令)获得最大值,看看是否不会剥香蕉皮。感谢您的建议,我已经投票给你们中的一些人作为亚军。 :)

最佳答案

fabs 和比较对于 IEEE float 来说都非常快(例如,原则上快速的单整数运算)。

如果编译器没有内联这两个操作,那么要么戳它直到它内联,要么找到你的架构的实现并自己内联它。

您也许可以从以下事实中得到一些东西:正数 IEEE float 与具有相同位模式的整数的顺序相同。也就是说,

f > g   iff   *(int*)&f > *(int*)&g

因此,一旦您完成了 fabs,我认为 int 的无分支最大值也适用于 float(当然假设它们的大小相同)。这里解释了为什么这有效:http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm .但是你的编译器和你的 CPU 已经知道所有这些,所以它可能没有任何区别。

没有更复杂的方法可以做到这一点。您的算法已经是 O(n),您无法击败它并仍然查看每个样本。

我想您的处理器的 SIMD(即 Intel 上的 SSE2)中可能有一些东西会有所帮助,因为每个时钟周期处理的数据比您的代码多。但我不知道是什么。如果有,那么它很可能会快几倍。

您可能会在多核 CPU 上进行并行处理,尤其是因为您要处理 40 个独立的数据流。这最多会快一些。 “只是”启动适当数量的额外线程,在它们之间分配工作,并使用您可以使用的最轻量级原语来指示它们何时全部完成(可能是线程屏障)。我不太清楚你是在绘制所有 40 个流的最大值,还是分别绘制每个流的最大值,所以也许你实际上不需要同步工作线程,除了确保结果传递到下一阶段没有数据损坏。

可能值得看一下反汇编,看看编译器展开了多少循环。试着再展开一点,看看是否有任何不同。

另一件需要考虑的事情是您获得了多少缓存未命中,以及是否可以通过为缓存提供一些线索来减少数量,以便它可以提前加载正确的页面。但我没有这方面的经验,我不会抱太大希望。 __builtin_prefetch 是 gcc 上的魔法咒语,我猜第一个实验类似于“在进入该 block 的循环之前预取下一个 block 的开头”。

您目前处于所需速度的多少百分比?还是“越快越好”?

关于c++ - float 组的更快 abs-max,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/817604/

有关c++ - float 组的更快 abs-max的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  3. ruby-on-rails - 事件记录 : Select max of limit - 2

    我正在尝试将以下SQL查询转换为ActiveRecord,它正在融化我的大脑。deletefromtablewhereid有什么想法吗?我想做的是限制表中的行数。所以,我想删除少于最近10个条目的所有内容。编辑:通过结合以下几个答案找到了解决方案。Temperature.where('id这给我留下了最新的10个条目。 最佳答案 从您的SQL来看,您似乎想要从表中删除前10条记录。我相信到目前为止的大多数答案都会如此。这里有两个额外的选择:基于MurifoX的版本:Table.where(:id=>Table.order(:id).

  4. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  5. ruby - 鸭子输入字符串、符号和数组的优雅方式? - 2

    这是针对我无法破坏的现有公共(public)API,但我确实希望对其进行扩展。目前,该方法采用字符串或符号或任何其他在作为第一个参数传递给send时有意义的内容我想添加发送字符串、符号等列表的功能。我可以只使用is_a吗?数组,但还有其他发送列表的方法,这不是很像ruby​​。我将调用列表中的map,所以第一个倾向是使用respond_to?:map。但是字符串也会响应:map,所以这行不通。 最佳答案 如何将它们全部视为数组?String的行为与仅包含String的Array相同:deffoo(obj,arg)[*arg].eac

  6. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  7. ruby - 如何更快地解决 project euler #21? - 2

    原始问题Letd(n)bedefinedasthesumofproperdivisorsofn(numberslessthannwhichdivideevenlyinton).Ifd(a)=bandd(b)=a,whereab,thenaandbareanamicablepairandeachofaandbarecalledamicablenumbers.Forexample,theproperdivisorsof220are1,2,4,5,10,11,20,22,44,55and110;therefored(220)=284.Theproperdivisorsof284are1,2,

  8. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

  9. ruby - 将 ruby​​ 哈希转换为数组的最佳方法是什么 - 2

    我有一个像这样的ruby​​散列{"stuff_attributes"=>{"1"=>{"foo"=>"bar","baz"=>"quux"},"2"=>{"foo"=>"bar","baz"=>"quux"}}}我想把它变成一个看起来像这样的散列{"stuff_attributes"=>[{"foo"=>"bar","baz"=>"quux"},{"foo"=>"bar","baz"=>"quux"}]}我还需要保留键的数字顺序,并且键的数量是可变的。上面是super简化的,但我在底部包含了一个真实的例子。执行此操作的最佳方法是什么?附言还需要递归就递归而言,这是我们可以假设的:1)

  10. ruby - Sinatra + Heroku + Datamapper 使用 dm-sqlite-adapter 部署问题 - 2

    出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t

随机推荐