如果SSE / AVX寄存器的值是所有字节都是0或1,有没有办法有效地获得所有非零元素的索引?
@H_404_2@例如,如果xmm值是
| r0 = 0 | r1 = 1 | r2 = 0 | r3 = 1 | r4 = 0 | r5 = 1 | r6 = 0 | … | r14 = 0 | r15 = 1 |
结果应该是(1,3,5,…,15).结果应放在另一个_m128i变量或char [16]数组中. @H_404_2@如果有帮助,我们可以假设寄存器的值是所有字节都是0或某个常量非零值(不是必需的1). @H_404_2@我非常想知道是否有关于那个或最好是C/C++内在的指令.在任何SSE或AVX指令集中. @H_404_2@编辑1: @H_404_2@这是正确的observed by @zx485原始问题不够清楚.我一直在寻找任何“连续”的解决方案. @H_404_2@上面的示例0 1 0 1 0 1 0 1 …应该导致以下任一情况: @H_404_2@>如果我们假设索引从1开始,则0将是终止字节,结果可能是
| r0 = 0 | r1 = 1 | r2 = 0 | r3 = 1 | r4 = 0 | r5 = 1 | r6 = 0 | … | r14 = 0 | r15 = 1 |
结果应该是(1,3,5,…,15).结果应放在另一个_m128i变量或char [16]数组中. @H_404_2@如果有帮助,我们可以假设寄存器的值是所有字节都是0或某个常量非零值(不是必需的1). @H_404_2@我非常想知道是否有关于那个或最好是C/C++内在的指令.在任何SSE或AVX指令集中. @H_404_2@编辑1: @H_404_2@这是正确的observed by @zx485原始问题不够清楚.我一直在寻找任何“连续”的解决方案. @H_404_2@上面的示例0 1 0 1 0 1 0 1 …应该导致以下任一情况: @H_404_2@>如果我们假设索引从1开始,则0将是终止字节,结果可能是
@H_404_2@002 004 006 008 010 012 014 016 000 000 000 000 000 000 000 000@H_404_2@>如果我们假设负字节是终止字节,结果可能是
@H_404_2@001 003 005 007 009 011 013 015 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF@H_404_2@>任何东西,它给出一个连续的字节,我们可以将其解释为原始值中非零元素的索引 @H_404_2@编辑2: @H_404_2@实际上,正如@harold和@Peter Cordes在对原始帖子的评论中所建议的那样,可能的解决方案之一是首先创建一个掩码(例如使用pmovmskb)并检查那里的非零索引.但这将导致循环.
解决方法
如果您希望结果数组被“压缩”,那么您的问题就方面尚不清楚. “压缩”的意思是,结果应该是连续的.因此,例如对于0 1 0 1 0 1 0 1 …,有两种可能性:
@H_404_2@不连续的:
@H_404_2@XMM0: 000 001 000 003 000 005 000 007 000 009 000 011 000 013 000 015@H_404_2@连续的:
@H_404_2@XMM0: 001 003 005 007 009 011 013 015 000 000 000 000 000 000 000 000@H_404_2@连续方法的一个问题是:您如何确定它是索引0还是终止值? @H_404_2@我正在为第一个非连续方法提供一个简单的解决方案,它应该非常快:
.data ddqZeroToFifteen db 0,1,2,4,6,7,8,9,10,11,12,13,14,15 ddqTestValue: db 0,1 .code movdqa xmm0,xmmword ptr [ddqTestValue] pxor xmm1,xmm1 ; zero XMM1 pcmpeqb xmm0,xmm1 ; set to -1 for all matching pandn xmm0,xmmword ptr [ddqZeroToFifteen] ; invert and apply indices@H_404_2@仅仅为了完整性:第二个是连续的方法,在这个答案中没有涉及.