aneira eficiente de converter índices de dispersão em índices de colet
Estou tentando escrever uma compactação de fluxo (pegue uma matriz e livre-se de elementos vazios) com intrínsecas SIMD. Cada iteração do loop processa 8 elementos por vez (largura do SIMD
om intrínsecas SSE, eu posso fazer isso de forma bastante eficiente com _mm_shuffle_epi8 (), que faz uma pesquisa na tabela de 16 entradas (reunida na terminologia de computação paralela). Os índices de reprodução aleatória são pré-computados e procurados com uma máscara de bit
for (i = 0; i < n; i += 8)
{
v8n_Data = _mm_load_si128(&data[i]);
mask = _mm_movemask_epi8(&is_valid[i]) & 0xff; // is_valid is byte array
v8n_Compacted = _mm_shuffle_epi8(v16n_ShuffleIndices[mask]);
_mm_storeu_si128(&compacted[count], v8n_Compacted);
count += bitCount[mask];
}
Meu problema agora é que eu gostaria de implementar isso também para o Altivec SIMD (não pergunte por que - decisão comercial equivocada). A Altivec não tem um equivalente a _mm_movemask_epi8 (), um ingrediente crítico. Então, precisarei encontrar uma maneira de
emulate _mm_movemask_epi8 () - parece caro, vários turnos e ORs
gere diretamente os índices de reprodução aleatória de forma eficiente -
namely, index i será o índice do i-ésimo elemento válido nos dados não compactados
element_valid: 0 0 1 0 1 0 0 1 0
gather_indices: x x x x x x 6 4 1
scatter_indices: 3 3 2 2 1 1 1 0 0
É simples fazer isso em série, mas preciso que seja paralelo (SIMD). Parece fácil gerar índices de dispersão com uma soma de prefixo, mas como nem o AltiVec nem o SSE têm uma instrução de dispersão, preciso reunir índices. Os índices de coleta são a função inversa dos índices de dispersão, mas como isso pode ser obtido em paralelo? Eu sei nos dias pioneiros da programação de GPU,conversão de dispersão para coleta era uma técnica comum, mas nenhum dos dois métodos descritos parece prátic
Talvez, se não insistir que a compactação preserva a ordem dos elementos, permitirá uma implementação mais eficiente? Eu posso desistir diss