• Nenhum resultado encontrado

6.2 Implementa¸c˜ ao das tabelas de memoriza¸c˜ ao

6.2.1 NRT Node Reuse Table

A tabela ou cache NRT ´e uma tabela de memoriza¸c˜ao utilizada para armazenar valores de entrada e sa´ıda de n´os v´alidos para o re´uso no grafo dataflow. Para o r´apido acesso dos seus elementos, utilizamos uma estrutura de particionamento baseada em hashs dos valores de entrada dos n´os. Esta possui os seguintes campos:

• Indx : N´umero de parti¸c˜ao da tabela de memoriza¸c˜ao.

• Inp Op: Operandos de entrada utilizados na execu¸c˜ao do n´o. • Out Op: Operandos de sa´ıda produzidos pela execu¸c˜ao do n´o. • Node ID : Identificador num´erico ´unico do n´o.

• Node Group ID: Identificador num´erico ´unico do grupo ao qual o n´o executado pertence.

• Node Type: Nome da tarefa que o n´o implementa, semelhante a um mnemˆonico de instru¸c˜ao.

O campo Indx ´e constru´ıdo a partir dos operandos de entrada do n´o. Esses operandos s˜ao serializados em uma string de bytes. Como a Sucuri ´e implementada em python, utilizamos o m´etodo cPickle para realizar a serializa¸c˜ao. A string ´e convertida em um hexadecimal atrav´es de uma fun¸c˜ao de hash md5, ap´os isso, o hexadecimal ´e convertido em um inteiro decimal. Uma opera¸c˜ao de m´odulo ´e realizada entre este valor e o n´umero de parti¸c˜oes da NRT.

Quando uma opera¸c˜ao de busca na tabela ´e feita para os operandos de entrada de um n´o, a convers˜ao hash utilizada para calcular o campo Indx ´e realizada sobre estes operandos. O valor inteiro gerado a partir da convers˜ao ´e utilizado para acessar a NRT. Isso garante um acesso mais r´apido `a NRT, pois apenas um subconjunto de entradas desta tabela ser˜ao verificados para validar a redundˆancia do n´o. Isto foi implementado na Sucuri para otimizar o acesso `a tabela durante as simula¸c˜oes de execu¸c˜oes.

A figura 6.2 apresenta este processo de transforma¸c˜ao para definir a parti¸c˜ao em que a entrada da NRT ser´a armazenada. O quadro ”A”mostra o n´o do grafo recebendo 3 operandos de entrada (a, b, c) e produzindo o operando d. `A esquerda de ”A”, vemos o processo de transforma¸c˜ao do valor (a, b, c) em um inteiro a ser utilizado como n´umero de parti¸c˜ao de uma NRT que possui 10 parti¸c˜oes. O processo inicia com a cria¸c˜ao de uma string de bytes utilizando a classe cPickle. A seguir, um c´odigo hash md5 convertido para decimal ´e gerado, e, por fim, a opera¸c˜ao de m´odulo entre este valor e a quantidade de parti¸c˜oes na NRT, calcula o n´umero da parti¸c˜ao na qual esta entrada dever´a ser armazenada. O quadro ”C”apresenta o registro armazenado com os dados da execu¸c˜ao do n´o 2.

Os campos Node ID, Node Group ID e Node Type s˜ao utilizados para identificar os n´os redundantes em trˆes esquemas distintos de implementa¸c˜ao da NRT: (i) NRT global (GNRT), (ii) NRT compartilhada (SNRT) e (iii) NRT local (LNRT).

Figura 6.2: Esquema de particionamento da NRT na Sucuri.

NRT Global

A NRT global consiste em uma ´unica tabela NRT que possui os valores de entrada e sa´ıda para todos os n´os do grafo. Portanto, um n´o com todos os seus operandos de entrada dispon´ıveis, antes de executar, ir´a consultar a tabela NRT para verificar se o seu resultado j´a foi memorizado por ele mesmo ou por algum outro n´o do grafo que implemente a mesma fun¸c˜ao que ele.

Note que, ao contr´ario das arquiteturas tradicionais, a tabela de memoriza¸c˜ao n˜ao ´e indexada por um campo de contador de programas, ao inv´es disso, ´e utilizado somente o tipo do n´o e os valores de entrada do mesmo para encontrar o registro memorizado. Em implementa¸c˜oes de re´uso em arquiteturas tradicionais de Von Neumann, ´e interessante utilizar o PC como indexador da tabela por este prover um r´apido acesso, como tamb´em, ser necess´ario na atualiza¸c˜ao de preditores de desvios e outras estruturas globais da m´aquina. Portanto, neste modelo, uma instru¸c˜ao do tipo add, por exemplo, n˜ao pode reutilizar outra instru¸c˜ao do mesmo tipo, caso possuam endere¸cos diferentes. Por n˜ao haver PC no paradigma dataflow, o re´uso ´e potencializado, pois ele ocorre para diferentes instru¸c˜oes do mesmo tipo, ao inv´es de instru¸c˜oes de um mesmo endere¸co.

A figura 6.3 apresenta o esquema de implementa¸c˜ao global da NRT na Sucuri. Note que todos os n´os possuem seus resultados escritas em uma ´unica tabela, o que permite que n´os distintos, mas que implementem a mesma fun¸c˜ao, utilizem resultados produzidos por eles entre si. Repare que a unidade de casamento provˆe uma entrada de um n´o pronto para execu¸c˜ao `a NRT para que uma busca seja feita.

Figura 6.3: Organiza¸c˜ao do escalonador central da Sucuri com uma NRT global.

Se o resultado desta entrada for conhecido, ele ´e retornado `a unidade de casamento para que seja propagado aos n´os dependentes. Caso contr´ario, uma entrada ´e criada na NRT, e a tarefa ´e instanciada a paritr do n´o que estava pronto para executar. NRT Compartilhada

O esquema de implementa¸c˜oes de NRTs compartilhadas consiste em implementar diferentes NRTs que ser˜ao utilizadas por grupos de n´os distintos. Isto se assemelha `

a processadores multicores com organiza¸c˜oes de caches locais L1 e L2 por n´ucleo. No momento de cria¸c˜ao de grafos na Sucuri, cada n´o ´e associado a um identifica- dor (Node ID ). De forma semelhante, tamb´em podemos associar cada n´o ao identi- ficador de um grupo (Node group ID ). Nesta primeira implementa¸c˜ao da DF-DTM, utilizamos uma metodologia simples para associa¸c˜ao de n´os aos grupos atrav´es de opera¸c˜oes m´odulo. A metodologia consiste em, dado uma quantidade n de NRTs, o grupo associado ao n´o de Node ID id ´e dado por mod(N odeid, n). Por exemplo, em uma implementa¸c˜ao com 4 NRTs, o n´o 101 seria associado ao grupo mod(101, 4) = 1, ou seja, este n´o escreveria e leria os resultados de suas opera¸c˜oes na NRT-1. Um esquema de NRTs compartilhadas com n NRTs ´e denominado de (S, n), onde S identifica um esquema de NRT compartilhada, e n a quantidade de NRTs utilizadas na implementa¸c˜ao.

A figura 6.4 apresenta um esquema de NRT (S, 3). Note que os n´os s˜ao orga- nizados em grupos distintos e a visibilidade de re´uso deles est´a limitada `a cache a qual o grupo est´a associado. Esta associa¸c˜ao ´e representada na figura pela faixa azul que envolve os n´os do grafo e o n´umero n na NRT-n. Por exemplo, os n´os 4 e 5 pertencem ao grupo 1 e ir˜ao ler e escrever na NRT-1. Se o n´o 4 possuir operandos de entrada cujo os resultados foram produzidos anteriormente somente pelo n´o 2, o

n´o 4 n˜ao ser´a detectado como redundante, pois n˜ao possui acesso `a NRT-2.

Figura 6.4: Organiza¸c˜ao do escalonador central da Sucuri com 3 NRTs comparti- lhadas (S, 3).

NRT Local

Um esquema de implementa¸c˜ao com NRT locais se assemelha `as estrat´egias de re´uso em arquiteturas tradicionais, onde instru¸c˜oes somente reutilizam resultados criados por elas. Neste cen´ario, s˜ao criadas n NRTs, e cada n´o do grafo possui uma tabela de memoriza¸c˜ao pr´opria. Pode-se dizer que esse esquema ´e uma especifica¸c˜ao do esquema de NRTs compartilhadas, onde o n´umero de caches ´e igual ao n´umero de n´os do grafo. Neste cen´ario o identificador do n´o ´e utilizado para acessar a NRT.

Figura 6.5: Organiza¸c˜ao do escalonador central da Sucuri com NRTs locais. A figura 6.5 apresenta este esquema de uso das NRTs para um grafo com 5 n´os. Note que cada n´o possui uma cache dedicada a si, reduzindo poss´ıveis conten¸c˜oes,

por´em diminuindo o escopo de visibilidade dos mesmos. Por exemplo, o n´o 1 ir´a ler e escrever somente na cache NRT-1.