【发布时间】:2017-05-20 23:16:10
【问题描述】:
我想使用 SSE 内在函数翻译此代码。
我找到了pshufbSSSE3 指令和类似的__builtin_ia32_pshufb128(v128i, v128i) GCC 内在函数,它们可能与此代码一起使用。
该代码通过以特定方式交换数组中的字节,通过索引k 置换字节向量s。
void permutation(int k, std::vector<char> & s)
{
for(size_t j = 1; j < s.size(); ++j)
{
std::swap(s[k % (j + 1)], s[j]);
k = k / (j + 1);
}
}
我花了一个小时思考如何将代码翻译成pshufb。是否可以使用单个 pshufb 置换 16 字节,还是需要多条指令?足够好的解决方案一次只置换 16 个字节。
编辑:问题的进一步背景:我正在迭代s 的所有可能排列。提前计算k = 0, 1, 2,... 相同s 的多个结果是可以的。但是我需要稍后重现k-th 排列,最好是 O(1) 操作。
【问题讨论】:
-
k的可能值范围是多少?s的典型尺寸是多少? -
此链接应该提供您想知道的所有内容:msdn.microsoft.com/en-us/library/bb531427(v=vs.120).aspx
-
这是一个相当奇怪的排列。对于所有
j这样j! >k,这将只是将s[j]与s[0]交换,这将插入只是将原始s[j]向上移动一个,并将最后一个留在s[0]中。 -
即使您使用的是 64 位整数(不太可能),这对于所有
j> 20 都是正确的。对于 32 位整数,对于所有j> 12 都是正确的. 如果您要置换大于该值的向量,您可能希望在 k == 0 时中断,并对剩余的幻灯片使用 memmove。如果您置换的向量少于此值,我很难相信这是您的性能瓶颈。 -
s的典型大小是 16 字节的倍数。仅针对 16 个字节的解决方案是可以的。k索引在相当紧密的循环中递增,直到置换结果符合某些条件或k会溢出。我还根据条件限制k的大小。