A pergunta a seguir está relacionada, no entanto, as respostas são antigas e os comentários do usuário Marc Glisse sugerem que existem novas abordagens desde o C ++ 17 para esse problema que talvez não sejam discutidas adequadamente.
Estou tentando fazer com que a memória alinhada funcione corretamente para o SIMD, enquanto ainda tenho acesso a todos os dados.
Na Intel, se eu criar um vetor flutuante do tipo __m256
e reduzir meu tamanho em um fator de 8, isso me dará uma memória alinhada.
Por exemplo std::vector<__m256> mvec_a((N*M)/8);
De uma maneira um pouco invasiva, posso converter ponteiros em elementos vetoriais para flutuar, o que me permite acessar valores de flutuação individuais.
Em vez disso, eu preferiria ter um std::vector<float>
que esteja alinhado corretamente e, portanto, possa ser carregado em __m256
e outros tipos de SIMD sem segfaulting.
Eu estive procurando em align_alloc .
Isso pode me dar uma matriz de estilo C que está alinhada corretamente:
auto align_sz = static_cast<std::size_t> (32);
float* marr_a = (float*)aligned_alloc(align_sz, N*M*sizeof(float));
No entanto, não tenho certeza de como fazer isso std::vector<float>
. Dar a std::vector<float>
propriedade de marr_a
não parece ser possível .
Eu já vi algumas sugestões de que eu deveria escrever um alocador personalizado , mas isso parece dar muito trabalho, e talvez com o C ++ moderno haja uma maneira melhor?
_mm256_loadu_ps(&vec[i])
. (Embora nota que, com opções de ajuste padrão, GCC divide não-garantida alinhado 256 bits cargas / lojas em vmovups XMM / vinsertf128. Portanto, não é uma vantagem de usar_mm256_load
maisloadu
se você se preocupa sobre como seus compila o código no GCC se alguém se esquece de uso-mtune=...
ou-march=
opções.)Respostas:
Todos os contêineres na biblioteca C ++ padrão, incluindo vetores, têm um parâmetro de modelo opcional que especifica o alocador do contêiner e não é muito trabalhoso implementar seu próprio:
Você precisará escrever um pouco de código que implementa seu alocador, mas não seria muito mais código do que você já escreveu. Se você não precisar de suporte pré-C ++ 17, precisará implementar apenas os métodos alocar () e desalocar () , é isso.
fonte
allocator_traits
vector<float, MAA>
não é compatível com o tipovector<float>
(e não pode ser porque qualquer coisa que faça.push_back
em uma planilhastd::vector<float>
compilada sem esse alocador pode fazer uma nova alocação e copiar para a memória minimamente alinhada.E new / delete não é compatível com align_alloc / free)std::vector
matriz do. Por exemplo, eu poderia imaginar uma implementaçãostd::vector
usando apenas um ponteiro para a memória alocada que armazena o final / capacidade / alocador na memória antes do intervalo de valores. Isso poderia facilmente frustrar o alinhamento feito pelo alocador.std::vector
garante isso. É para isso que serve. Talvez você deva revisar o que o padrão C ++ especifica aqui.allocator_traits
- Não, não precisam . Tudo o que é necessário é implementar um alocador compatível.