我有一个过滤器m_f,它通过
v
Real d2v = m_f[0]*v[i];
for (size_t j = 1; j < m_f.size(); ++j)
{
d2v += m_f[j] * (v[i + j] + v[i - j]);
}
perf 告诉我们这个循环在哪里很热:
vaddpd 和vfma231pd 是有意义的;没有他们,我们肯定无法执行此操作。但是缓慢的 vpermpd 让我感到困惑。它有什么作用?
最佳答案
vpermpd 如果您的瓶颈是前端吞吐量(将 uops 馈送到无序核心),则只会在这里减慢您的速度。
vpermpd 并不是特别“慢”,除非您使用的是 AMD CPU。 (跨车道 YMM 洗牌在 AMD 的 CPU 上很慢,因为它们必须解码成比 256 位指令分成的正常 2 128 位微指令更多的代码。vpermpd 是 3 微指令Ryzen,或带有内存源的 4。)
在 Intel 上,具有内存源的 vpermpd 前端始终为 2 微指令(即使是非索引寻址模式也无法微融合)。布
如果您的循环只运行少量迭代,那么 OoO exec 可能能够隐藏 FMA 延迟,并且可能实际上是此循环前端和周围代码的瓶颈。这是可能的,考虑到循环外的(低效)水平求和代码得到了多少计数。
在那种情况下,也许按 2 展开会有所帮助,但检查是否可以运行主循环的一次迭代的额外开销对于非常小的计数可能会变得代价高昂。
否则(对于大量计数)您的瓶颈可能在于使用 d2v 作为输入/输出操作数 执行 FMA 的 4 到 5 个循环循环承载依赖性。展开多个累加器和指针增量而不是索引,将是一个巨大的性能胜利。比如 2 倍或 3 倍。
试试 clang,它通常会为您做这件事,而且它的 skylake/haswell 调整非常积极地展开。 (例如 clang -O3 -march=native -ffast-math)
带有 -funroll-loops 的 GCC 实际上并不使用多个累加器,IIRC。我有一段时间没看了,我可能是错的,但我认为它只会使用相同的累加器寄存器重复循环体,根本无助于并行运行更多的 dep 链。 Clang 实际上会使用 2 或 4 个不同的 vector 寄存器来保存 d2v 的部分和,并将它们添加到循环外的末尾。 (但对于大尺寸,8个或更多会更好。Why does mulss take only 3 cycles on Haswell, different from Agner's instruction tables?)
展开也使得使用指针增量变得有值(value),在英特尔 SnB 系列上的每个 vaddpd 和 vfmadd 指令中节省 1 uop。
为什么 m_f.size(); 保存在内存中 (cmp rax, [rsp+0x50]) 而不是寄存器? 您是否在禁用严格别名的情况下进行编译?循环不写入内存,所以这很奇怪。除非编译器认为循环将运行很少的迭代,否则不值得在循环外的代码加载最大值?
每次迭代都复制和取反 j 看起来像是错过了优化。显然,从循环外的 2 个寄存器开始效率更高,并且 add rax,0x20/sub rbx, 0x20 每次循环迭代而不是 MOV+NEG。
如果您对此有一个 [mcve],它看起来像是错过了几个可能被报告为编译器错误的优化。这个 asm 对我来说看起来像 gcc 输出。
令人失望的是 gcc 使用了如此糟糕的水平求和惯用语。 VHADDPD 为 3 微指令,其中 2 微指令需要随机端口。也许尝试更新版本的 GCC,例如 8.2。虽然我不确定避免 VHADDPS/PD 是否是关闭 GCC bug 80846 的一部分作为固定。该链接指向我对使用 packed-single 分析 GCC 的 hsum 代码的错误的评论,使用 vhaddps 两次。
看起来循环后的 hsum 实际上是“热”的,因此您正在遭受 gcc 紧凑但效率低下的 hsum 的困扰。
关于c++ - 正在生成缓慢的 vpermpd 指令;为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54384807/
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput