我希望使用每次计算4或8个数组元素的NEON功能来优化C++代码(主要是用于循环)。是否有某种库或一组函数可以在C++环境中使用?
我在Linux中使用Eclipse编写C++代码。
更新
在阅读了答案之后,我用软件做了一些测试。我使用以下标志编译了我的项目:
-O3 -mcpu=cortex-a9 -ftree-vectorize -mfloat-abi=hard -mfpu=neon 请记住,该项目包括广泛的库,如开放框架、OpenCV和OpenNI,并且所有内容都是用这些标志编译的。
为了编译ARM板,我们使用Linaro工具链交叉编译器,GCC的版本为4.8.3。
你希望这样做能提高项目的绩效吗?因为我们没有经历任何变化,考虑到我在这里读到的所有答案,这是相当奇怪的。
另一个问题是:所有for循环都有明显的迭代次数,但其中许多迭代是通过自定义数据类型(结构或类)进行的。GCC可以优化这些循环,即使它们遍历自定义数据类型吗?
发布于 2015-02-16 21:07:36
编辑:
从您的更新中,您可能误解了霓虹灯处理器的功能。它是一个SIMD (单指令,多数据)矢量处理器。这意味着它非常擅长于同时对多个数据执行指令(例如“乘4")。它还喜欢做“将所有这些数字加在一起”或“将这两个数字列表中的每一个元素相加以创建第三个数字列表”。所以,如果你的问题看起来像那些东西,霓虹灯处理器将是巨大的帮助。
为了获得这种好处,您必须将数据以非常特定的格式放置,这样向量处理器可以同时加载多个数据,并行处理,然后同时将其写回。您需要组织一些事情,这样的数学避免了大多数条件(因为看结果太快意味着往返到霓虹灯)。矢量编程是一种不同的思考你的程序的方式。这都是管道管理的问题。
现在,对于许多非常常见的问题,编译器可以自动解决所有这些问题。但它仍然是关于处理数字,以及特定格式的数字。例如,您几乎总是需要将所有数字放入内存中的连续块中。如果您正在处理结构和类中的字段,则霓虹灯无法真正帮助您。这不是一个通用的“并行工作”引擎。它是一个用于并行数学的SIMD处理器。
对于非常高性能的系统,数据格式就是一切。不采用任意的数据格式(结构、类等)试着让他们快点。您可以找出数据格式,使您能够完成最并行的工作,然后编写相应的代码。你的数据是连续的。您不惜一切代价避免内存分配。但这并不是一个简单的StackOverflow问题能够解决的问题。高性能编程是一套完整的技能,也是一种不同的思维方式。这不是通过找到正确的编译器标志而得到的。正如您所发现的,缺省值已经相当好了。
您应该问的真正问题是,您是否可以重新组织数据,以便更多地使用OpenCV。OpenCV已经有了很多优化的并行操作,这些操作几乎肯定会很好地利用霓虹灯。您希望尽可能地将数据保持在OpenCV工作的格式中。这很可能是你获得最大进步的地方。
我的经验是,手工编写霓虹灯组件当然是可能的,它将击败clang和gcc (至少从几年前开始,尽管编译器肯定在继续改进)。拥有优秀的手臂优化与霓虹灯优化是不同的。正如@Mats所指出的,编译器通常会在明显的情况下做出色的工作,但并不总是在理想的情况下处理每一种情况,当然,即使是技术不太熟练的开发人员也有可能有时击败它,有时甚至是戏剧性的。(@wallyk也是正确的,即手动调整程序集最好保存到最后;但它仍然非常强大。)
尽管如此,鉴于你的发言“大会,我绝对没有背景,也不可能负担得起在这一点上学习”,那么不,你甚至不应该麻烦。如果不首先了解程序集(特别是向量化霓虹灯程序集)的基本知识(和一些非基础知识),就没有必要对编译器进行事后猜测。击败编译器的第一步是知道目标。
如果你愿意学习的目标,我最喜欢的介绍是手臂装配的旋风巡游。再加上其他一些引用(下面),就足以让我在我的特殊问题上比编译器高出2-3倍。另一方面,当我向一位有经验的霓虹灯开发者展示我的代码时,他看了大约三秒,说“你在那里停了下来。”真正好的组装是困难的,但半体面的组装仍然可以比优化的C++更好。(同样,随着编译器编写人员的情况越来越好,这种情况每年都变得越来越少,但仍有可能是真的。)
一方面,我对霓虹灯本质的经验指出,它们很少值得麻烦。如果要击败编译器,则需要实际编写完整的程序集。大多数情况下,无论您使用什么内部特性,编译器都已经知道了。你获得权力的地方更多的是重组你的循环,以便最好地管理你的管道(而本质对此没有帮助)。这可能在过去几年中有所改善,但我希望改进的向量优化器的速度会超过本质的值,而不是相反。
发布于 2016-05-11 09:35:17
这里有一个"mee太“与一些博客文章来自ARM。FIRST,从以下获得背景信息开始,包括32位ARM (ARMV7及以下)、Aarch32 (ARMv8 32位ARM)和Aarch64 (ARMv8 64位ARM):
第二代,检查霓虹灯系列的编码。这是一个很好的介绍与图片,所以事情像交错的负载是有意义的一瞥。
我还在亚马逊( Amazon )上寻找一些有关ARM组装的书籍,并对霓虹灯进行处理。我只能找到两个,两本书对霓虹灯的处理都令人印象深刻。他们简化为一个章节与强制性矩阵的例子。
我相信Intrinsics是个很好的主意。该工具允许您编写GCC、Clang和Visual /C++编译器的代码。我们有一个代码库,适用于ARM Linux发行版(如Linaro)、一些iOS设备(使用-arch armv7)和微软小工具(如Windows和Windows应用程序)。
发布于 2015-02-16 20:36:35
除了沃利的回答--也许应该是一个评论,但我不能说得足够简短: ARM有一支编译器开发人员团队,他们的全部角色是改进GCC和Clang/llvm中为ARM CPU生成代码的部分,包括提供“自动向量化”的功能--我没有深入研究它,但从我在x86代码生成方面的经验来看,对于任何相对容易向量化的东西,编译器都应该完成一项任务。对于编译器来说,有些代码很难理解它何时可以向量化,并且可能需要一些“鼓励”--例如展开循环或将条件标记为“可能”或“不可能”等。
免责声明:我为ARM工作,但与编译器甚至GPU没有什么关系,就像我为图形组工作一样(在这里,我参与GPU驱动程序的OpenCL部分中GPU的编译器)。
编辑:
性能和各种指令扩展的使用实际上取决于代码所做的工作。我希望像OpenCV这样的库已经在它们的代码中做了相当多的聪明的事情(比如手工编写的汇编程序作为编译器的本质,一般的代码是为了让编译器已经做得很好),所以它可能不会给您带来多大的改进。我不是计算机视觉专家,所以我不能确切地评论在OpenCV上做了多少这样的工作,但我当然希望代码中的“最热门”点已经被很好地优化了。
另外,分析一下你的应用程序。不要只是摆弄优化标志,衡量它的性能,并使用一个分析工具(例如Linux "perf“工具)来衡量您的代码花在哪里的时间。然后看看能对特定的代码做些什么。是否可以编写一个更并行的版本呢?编译器能帮忙吗,你需要写汇编程序吗?是否有不同的算法做同样的事情,但以更好的方式等.
尽管调整编译器选项可能有帮助,而且经常如此,但它可以提供数十%,其中算法的更改通常会导致10倍或100倍更快的代码--当然,假设您的算法可以改进!
然而,了解应用程序的哪一部分花费时间是关键。如果在其他地方进行更改,代码就会比总时间快20%或30 %或60%,那么就没有必要修改代码,使代码的速度提高5% -- 10%。或者优化一些数学例程,当80%的时间花在读取一个文件上时,如果使缓冲区的大小增加一倍,它的速度就会提高一倍.
https://stackoverflow.com/questions/28547697
复制相似问题