Pergunta

Uma coisa que não descobri e o google não está me ajudando é por que é possível ter conflitos de banco na memória compartilhada, mas não na memória global?Pode haver conflitos bancários com registros?

ATUALIZARUau, eu realmente aprecio as duas respostas de Tibbit e Grizzly.Parece que só posso dar uma marca de seleção verde para uma resposta.Eu sou novato em stack overflow.Acho que tenho que escolher uma resposta como a melhor.Posso fazer algo para agradecer a resposta para a qual não dou um cheque verde?

Foi útil?

Solução

Resposta curta: Não há conflitos de banco nem na memória global nem nos registradores.

Explicação:

A chave para entender o porquê é compreender a granularidade das operações.Um único thread não acessa a memória global.Os acessos à memória global são "unidos".Como a memória global é muito lenta, qualquer acesso dos threads dentro de um bloco é agrupado para fazer o menor número possível de solicitações à memória global.

A memória compartilhada pode ser acessada por threads simultaneamente.Quando duas threads tentam acessar um endereço dentro do mesmo banco, isso causa um conflito de banco.

Os registros não podem ser acessados ​​por nenhum thread, exceto aquele ao qual estão alocados.Como você não pode ler ou escrever em meus registros, você não pode me impedir de acessá-los – portanto, não há conflitos bancários.

Quem pode ler e escrever na memória global?

Only blocks.Uma única thread pode fazer um acesso, mas a transação será processada em nível de bloco (na verdade, nível warp/half warp, mas estou tentando não ser complicado).Se dois blocos acessarem a mesma memória, não acredito que demore mais e isso pode acontecer acelerado pelo cache L1 nos dispositivos mais novos - embora isso não seja evidente de forma transparente.

Quem pode ler e escrever na memória compartilhada?

Any thread within a given block. Se você tiver apenas 1 thread por bloco não poderá ter conflito de banco, mas não terá desempenho razoável.Os conflitos bancários ocorrem porque um bloco é alocado com vários, digamos 512 threads, e todos estão competindo por endereços diferentes dentro do mesmo banco (não exatamente o mesmo endereço).Existem algumas imagens excelentes desses conflitos no final do Guia de Programação CUDA C - Figura G2, na página 167 (na verdade, página 177 do pdf). Link para a versão 3.2

Quem pode ler e escrever nos registros?

Only the specific thread to which it is allocated. Portanto, apenas um thread está acessando-o por vez.

Outras dicas

Se pode haver ou não conflitos bancários em um determinado tipo de memória depende obviamente da estrutura da memória e, portanto, de sua finalidade.

Então, por que a memória compartilhada é projetada de forma a permitir conflitos bancários?

Isso é relativamente simples, não é fácil projetar um controlador de memória que possa lidar com acessos independentes à mesma memória simultaneamente (comprovado pelo fato de que a maioria não consegue).Portanto, para permitir que cada thread em halfwarp acesse uma palavra endereçada individualmente, a memória é armazenada, com um controlador independente para cada banco (pelo menos é assim que se pode pensar, sem ter certeza sobre o hardware real).Esses bancos são intercalados para agilizar o acesso dos threads sequenciais à memória sequencial.Portanto, cada um desses bancos pode lidar com uma solicitação por vez, permitindo idealmente execuções simultâneas de todas as solicitações no halfwarp (obviamente, esse modelo pode, teoricamente, sustentar maior largura de banda devido à independência desses bancos, o que também é uma vantagem).

E os registros?

Os registradores são projetados para serem acessados ​​como operandos para instruções da ALU, o que significa que devem ser acessados ​​com latência muito baixa.Portanto, eles obtêm mais transistores/bit para tornar isso possível.Não tenho certeza de como exatamente os registros são acessados ​​nos processadores modernos (não é o tipo de informação que você precisa com frequência e não é tão fácil de descobrir).No entanto, seria obviamente altamente impraticável organizar registros em bancos (para arquiteturas mais simples, você normalmente vê todos os registros pendurados em um grande multiplexador).Então não, não haverá conflitos bancários por cadastros.

Memória global

Em primeiro lugar, a memória global funciona com uma granulação diferente da memória compartilhada.A memória é acessada em blocos de 32, 64 ou 128 bytes (pelo menos para GT200, para Fermi é sempre 128B, mas em cache, AMD é um pouco diferente), onde toda vez que você deseja algo de um bloco, todo o bloco é acessado/transferido.É por isso que você precisa de acessos unidos, pois se cada thread acessar a memória de um bloco diferente você terá que transferir todos os blocos.

Mas quem disse que não há conflitos bancários?Não tenho certeza disso, porque não encontrei nenhuma fonte real que suporte isso para hardware NVIDIA, mas parece lógico:A memória global é normalmente distribuída em vários chips RAM (o que pode ser facilmente verificado observando uma placa gráfica).Faria sentido se cada um desses chips fosse como um banco de memória local, então você teria conflitos de banco se houvesse várias solicitações simultâneas no mesmo banco.No entanto, os efeitos seriam muito menos pronunciados para uma coisa (já que a maior parte do tempo consumido pelos acessos à memória é a latência para obter os dados de A para B de qualquer maneira), e não será um efeito perceptível "dentro" de um grupo de trabalho (já que apenas um halfwarp é executado por vez e se esse halfwarp emitir mais de uma solicitação, você terá um acesso à memória não aglutinado, então você já está sofrendo um golpe, dificultando a medição dos efeitos desse conflito.Então você só teria conflitos se vários grupos de trabalho tentassem acessar o mesmo banco.Em sua situação típica para gpgpu, você tem um grande conjunto de dados na memória sequencial, portanto os efeitos não devem ser notados, pois há outros grupos de trabalho suficientes acessando os outros bancos ao mesmo tempo, mas deve ser possível construir situações em que o conjunto de dados está centrado em apenas alguns bancos, o que representaria um impacto na largura de banda (uma vez que a largura de banda máxima viria da distribuição igualitária do acesso em todos os bancos, de modo que cada banco teria apenas uma fração dessa largura de banda).Novamente, não li nada para provar essa teoria para o hardware da Nvidia (quase tudo se concentra na coalescência, o que é mais importante, pois torna isso um problema para os conjuntos de dados naturais).No entanto, de acordo com o guia de computação ATI Stream, esta é a situação das placas Radeon (para 5xxx:os bancos estão separados por 2kb e você quer ter certeza de distribuir seus acessos (ou seja, de todos os grupos de trabalho simuladamente ativos) igualmente entre todos os bancos), então imagino que as placas NVidia se comportem de maneira semelhante.

É claro que para a maioria dos cenários a possibilidade de conflitos bancários na memória global não é um problema, então na prática você pode dizer:

  • Fique atento à coalescência ao acessar a memória global
  • Fique atento a conflitos bancários ao acessar a memória local
  • Sem problemas com acesso aos registros

Vários tópicos que acessam o mesmo banco não significa necessariamente que há um conflito bancário. Há um conflito se os threads quiserem ler ao mesmo tempo de uma linha diferente dentro do mesmo banco.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top