我正在尝试在预定值和数组的每个元素之间执行bitwise XOR
。
这显然可以在这样的循环中完成(在伪代码中):
int scalar = 123;
for(int i = 0; i < VECTOR_LENGTH; i++) {
int x_or = scalar ^ a[i];
}
但我开始使用Accelerate.framework
了解性能增强。
我正在查看Accelerate.framework
的文档,但我还没有看到基于bitwise XOR
的元素。 有人知道这是否可行?
答案 0 :(得分:3)
加速并未实施相关操作。但是,您可以非常轻松地编写自己的矢量代码。一旦好的方法是使用clang矢量扩展:
#include <stddef.h>
typedef int vint8 __attribute__((ext_vector_type(8),aligned(4)));
typedef int vint4 __attribute__((ext_vector_type(4),aligned(4)));
typedef int vint2 __attribute__((ext_vector_type(2),aligned(4)));
int vector_xor(int *x, size_t n) {
vint8 xor8 = 0;
while (n >= 8) {
xor8 ^= *(vint8 *)x;
x += 8;
n -= 8;
}
vint4 xor4 = xor8.lo ^ xor8.hi;
vint2 xor2 = xor4.lo ^ xor4.hi;
int xor = xor2.lo ^ xor2.hi;
while (n > 0) {
xor ^= *x++;
n -= 1;
}
return xor ^ 123;
}
这非常好,因为(a)它不需要使用内在函数,(b)它不会将您与任何特定的架构联系起来。它为您编译的任何体系结构生成相当不错的代码。另一方面,它将您绑定到clang
,而如果您使用内在函数,则您的代码也可以与其他编译器一起使用。
答案 1 :(得分:2)
斯蒂芬的答案很有用,但是当你在考虑加速时,请记住它不是一个神奇的“快速”库。除非VECTOR_LENGTH非常大(比如10,000 - 编辑:斯蒂芬不同意这种规模,并且往往比我更了解这个主题;看到评论),函数调用的成本往往会压倒你获得的任何好处。请记住,在一天结束时,Accelerate只是代码。很多时候,像你这样简单的手写循环(尤其是编译器优化很好)在xor这样的简单操作上会变得更好或更好。
但在许多情况下,您需要让编译器帮助您。 Clang知道如何自动执行各种有用的向量优化(就像在Stephen的回答中一样)。但在大多数情况下,默认优化设置是-Os(最快,最小)。这就是说“铿锵,你可以做任何你想要的优化,但如果它使得生成的二进制文件更大,那就不行了。”你可能会注意到斯蒂芬的例子比你的大一点。这意味着编译器经常被禁止应用它知道如何操作的自动向量优化。
但是,如果你切换到-Ofast,那么你给clang权限来提高性能,即使它增加了二进制大小(在现代硬件上,甚至是移动硬件上,这通常是一个非常好的权衡)。在“构建设置”面板中,这称为“优化级别:最快,最具侵略性的优化”。几乎在所有情况下,这都是iOS和OS X应用程序的正确设置。 (由于历史原因,它目前不是默认值;我希望Apple将来会将其作为默认设置。)
有关Accelerate(精彩图书馆)限制的更多讨论,您可能会对"Introduction to Fast Bézier (and Trying the Accelerate.framework)"感兴趣。我还强烈推荐"What's New in the LLVM Compiler"(WWDCS 2013的会话402),我发现它比Accelerate的介绍更有用。如果你不走的话,Clang可以做一些非常惊人的优化。