对于基于八叉树的稀疏体素八叉树渲染器,我希望能够旋转并镜像八叉树的各个节点。尽管它实际上不是八叉树,但由于节点被共享并被允许将自己包含为子树。否则,我可以简单地将转换应用于八叉树本身。
在不失一般性的前提下,假定该多维数据集是一个单位多维数据集,其原点为一个角(0,0,0),而对角为(1,1,1)。我已经将立方体的角编码为3位整数。所以0(= 0b000)代表原点的角,1(= 0b001)代表(0,0,1)的角,而7(= 0b111)代表(1,1,1)的角。唯一允许的旋转和反射是围绕立方体的中心(1/2,½,½),这样拐角将以整数坐标结束。这意味着只有48种可能的转换。 (第一个角可以映射到8个可能的位置,下一个角可以映射到3个,第三个角可以映射到2个,这将固定其余角的位置。)
我还没有决定如何编码转换,尽管应该可以将其编码为单个32位整数(或者甚至是6位整数,因为只有48种可能的转换)。然后可以将变换用作函数,该函数将变换后的多维数据集的每个角映射到其位置。即
int transform(int corner, int transformation) {
// magic happens here
return result;
}
此外,我还应该具有合并转换的函数combine
,以便transform(corner, combine(a,b))
等于transform(transform(corner, b), a)
。
由于这些函数每秒将被调用十亿次,因此它们应该很快。虽然变换将被称为合并的大约4倍。该算法是递归的,因此,如果转换编码使用多个32位整数,则将其放入堆栈时会产生额外的运行时成本。
到目前为止,我已经发现问题可以分解为位翻转,这可以通过单个异或运算和位置换来完成(我尚不知道如何有效地完成)。但是,同时执行这两个操作的效率可能更高。
我打算在已经使用SSE4.1内部函数的C ++代码中使用它。尽管不使用内部函数或仅需要SSE3的解决方案是首选。最后,速度是最重要的。我将尝试使用http://quick-bench.com/比较解决方案。
((注意:我使用了affinetransform标记,因为没有正交转换标记,并且我不想创建它)。
您可以将转换存储为8个字节的数组,该数组对多维数据集角的排列进行编码。 transform
方法就像数组查找一样简单。将这些转换中的两个转换组合在一起可以循环进行,但这会很慢。但是,事实证明SSSE3具有在单个指令中执行此操作的内在函数:_mm_shuffle_pi8
。
因此可以按如下方式实现必要的方法:
_mm_shuffle_pi8
根据我的基准测试结果,我得到了四次调用transform并合并一次的调用,这花费了大约2ns的CPU时间。这仍然有点慢,但是如果有足够的内核,这可能是可行的。
我还实现了一些不同的比较方法:
#include <tmmintrin.h>
__m64 transform(int corner, __m64 transformation) {
uint8_t array[8];
memcpy(array, &transformation, 8); // This call is optimized away by the compiler.
return array[corner];
}
__m64 combine(T a, T b) {
return _mm_shuffle_pi8(b, a);
}
的结果。使用一半的内存时,速度要慢3-5倍。我创建了一个combine
,尽管它不支持使用SSSE3指令,所以我不得不禁用使用quick-bench page的方法。您仍然可以在本地编译和运行它们。