Memória transacional: o que é e integração via Intel TSX

Memória Transacional

Boa parte do poder de nossos PCs está baseado na divisão do trabalho, onde vários elementos compartilham a execução de uma parte do código para trabalhar com ele. Mas às vezes há conflitos no acesso a dados e instruções que se tornam um problema de desempenho. Uma maneira de corrigir isso é a memória transacional.

Um dos maiores problemas com o multicore CPU sistemas que nossos PCs usam é que eles são baseados no modelo de Von Neumann, que é que há apenas um poço de memória compartilhada. Conforme aumenta o número de unidades de execução, núcleos, threads e outros elementos que funcionam em paralelo em uma CPU. Mais e mais conflitos são criados entre eles. Não só no acesso aos dados, mas também nas informações contidas nos diferentes endereços de memória e, portanto, no valor das variáveis ​​utilizadas pelos programas. Existem muitos métodos para evitar esses conflitos, um deles é a memória transacional, que iremos descrever neste artigo.

Uma introdução ao problema

Cerrojos

Ao escrever um programa, ele é codificado em uma série de instruções que aparentemente são executadas sequencialmente. Mas já com o paralelismo das instruções com um único kernel no meio da execução, podem entrar diferentes unidades de execução. Para isso devemos levar em consideração que a execução fora de ordem acrescenta a complexidade de que o acesso à memória e aos dados em tempo de execução seja feito de forma desordenada.

Quando há um grande número de solicitações, acaba gerando uma contenção para acessar a mesma memória. Isso faz com que as solicitações sejam atrasadas cada vez mais, aumentando a latência da memória com a CPU em certas instruções e afetando a largura de banda. Para isso, existem mecanismos que evitam ao máximo esses conflitos no acesso à memória, de forma que os processos acessem a memória a partir da memória ordenada. Isso evita conflitos ao modificar os dados em sua hierarquia, além de reduzir problemas de contenção e consequentemente a latência de acesso.

A maneira mais simples de conseguir isso é por meio de travas, que são seções do código onde marcamos que não precisam ser executadas simultaneamente por diferentes threads da CPU. Ou seja, apenas um núcleo dele pode ser responsável por esta parte do código. Portanto, fizemos um bloqueio para o resto dos núcleos e o resto só poderá entrar na execução quando a instrução que finaliza o bloqueio for alcançada. O que acontecerá quando a parte do código isolada para todos os núcleos, exceto um, for concluída.

O que é memória transacional?

Código binário cor

Um método para evitar os problemas descritos na seção anterior é usar a memória transacional. O que não é um tipo de memória ou armazenamento, portanto, não estamos falando de uma peça de hardware pura. Sua origem está nas transações das bases de dados, é um tipo de instrução executada nas unidades Load-Store.

O sistema de transação em um processador funciona da seguinte maneira:

  1. É criada uma cópia da parte da memória que vários núcleos desejam acessar, um para cada instância.
  2. Cada instância modifica sua cópia privada independentemente do resto das cópias privadas.
  3. Se um dado foi modificado em uma cópia privada e não no resto, então a modificação também é copiada no resto das cópias privadas.
  4. Se duas instâncias fizerem uma alteração nos mesmos dados ao mesmo tempo e criar uma inconsistência nos dados, ambas as cópias privadas serão excluídas. e as cópias privadas do resto são copiadas

O quarto ponto é importante, pois é naquela parte onde fica claro que é necessário que essa parte do código seja serializada. Isso significa que o restante das instâncias param de modificar suas cópias privadas e as modificações são feitas por apenas uma das instâncias. Quando termina, as modificações são copiadas para o resto das cópias privadas. Quando a parte do código marcada como transacional já tiver sido executada e todas as cópias privadas contiverem as mesmas informações, o resultado será copiado nas linhas de cache e endereços de memória correspondentes.

Sistemas de memória transacional, o Intel TSX

Hardware Memoria Transaccional

A sigla TSX, Extensões de sincronização transacional, refere-se a uma série de instruções adicionais para o ISA x86, que se destinam a adicionar suporte de memória transacional para Intel CPUs. Portanto, é uma série de instruções e mecanismos associados a eles que permitem delimitar seções específicas do código como transacionais e para a CPU Intel realizar o processo que discutimos no processo anterior. Mas, neste caso, a implementação da Intel é um pouco mais complexa. Visto que, como vimos antes, se houver um conflito entre dois dados, todo o processo é abortado por uma das instâncias em execução.

Sua implementação em hardware é obtida adicionando-se um novo tipo de cache denominado cache transacional, no qual as diferentes operações são realizadas nos diferentes dados. Lembre-se de que o que a memória transacional busca é reduzir os conflitos ao acessar a memória. Embora os caches suportem uma quantidade maior de solicitações do que o RAM em geral, eles também são limitados e especialmente nos níveis mais distantes dos núcleos. Tudo isso aliado ao uso de memórias internas e registros privados que servem de suporte às cópias privadas executadas pelos diferentes núcleos.

As instruções Intel TSX não são um conjunto complexo, temos por um lado a instrução XBEGIN que nos marca quando uma seção transacional da memória começa, a instrução XEND que marca o fim e o XABORT, que serve para marcar uma saída do processo quando ocorre uma situação excepcional.

O fim das instruções do Intel TSX?

Cancelamento Intel TSX

As unidades de controle de CPU atuais são, na verdade, microcontroladores completos, o que significa que a maneira como ela decodifica as instruções e a lista de instruções pode ser atualizada. A Intel fez a primeira implementação na arquitetura Haswell e ela permaneceu dentro das CPUs da Intel até agora. Uma vez que foi recentemente desativado por meio de firmware nos próprios núcleos de sexta, sétima e oitava geração da Intel.

De vez em quando a Intel realiza atualizações remotas de suas CPUs, que são realizadas através do Intel Management Engine que temos em nosso PC sem que o saibamos. Normalmente não são comuns, mas podem incluir otimizações para a execução de certas instruções ou até mesmo a eliminação do suporte para outras. A eliminação do Intel TSX no Intel Core deve-se ao fato de que com as últimas modificações do microcódigo interno da unidade de controle há um conflito no funcionamento do software, o que significa que a CPU não funciona como deveria.

Mas a verdadeira razão é que o Intel TSX permite que códigos maliciosos sejam executados sob o radar dos sistemas de segurança clássicos, principalmente aqueles que afetam o sistema operacional. Já as cópias privadas não correspondem ao ambiente do usuário ou ao sistema operacional. Portanto, ainda é um problema semelhante ao da execução especulativa.