Fila de entrada de pré-busca - Prefetch input queue

Buscar os opcodes de instrução da memória do programa com bastante antecedência é conhecido como pré - busca e é servido usando a fila de entrada de pré-busca (PIQ). As instruções pré-buscadas são armazenadas na estrutura de dados - ou seja, uma fila . A busca de opcodes com bastante antecedência, antes de sua necessidade de execução, aumenta a eficiência geral do processador, aumentando sua velocidade. O processador não precisa mais esperar pelas operações de acesso à memória para que o opcode de instrução subsequente seja concluído. Essa arquitetura foi usada com destaque no microprocessador Intel 8086 .

Introdução

Pipelining foi trazido para a vanguarda do design de arquitetura de computação durante a década de 1960 devido à necessidade de uma computação mais rápida e eficiente. Pipelining é o conceito mais amplo e a maioria dos processadores modernos carregam suas instruções alguns ciclos de clock antes de executá-las. Isso é obtido através do pré-carregamento do código de máquina da memória em uma fila de entrada de pré - busca .

Esse comportamento se aplica apenas a computadores von Neumann (ou seja, não aos computadores da arquitetura Harvard ) que podem executar código de automodificação e ter algum tipo de pipelining de instruções . Quase todos os computadores modernos de alto desempenho atendem a esses três requisitos.

Normalmente, o comportamento de pré-busca do PIQ é invisível para o modelo de programação da CPU. No entanto, existem algumas circunstâncias em que o comportamento do PIQ é visível e precisa ser levado em consideração pelo programador.

Quando o processador x86 muda o modo de realmode para o modo protegido e vice-versa, o PIQ deve ser esvaziado, ou então a CPU continuará a traduzir o código de máquina como se ele tivesse sido escrito em seu último modo. Se o PIQ não for liberado, o processador pode traduzir seus códigos incorretamente e gerar uma exceção de instrução inválida .

Ao executar o código de auto-modificação , uma alteração no código do processador imediatamente antes do local atual de execução pode não alterar a forma como o processador interpreta o código, pois ele já está carregado em seu PIQ. Ele simplesmente executa sua cópia antiga já carregada no PIQ em vez da versão nova e alterada do código em sua RAM e / ou cache .

Este comportamento do PIQ pode ser usado para determinar se o código está sendo executado dentro de um emulador ou diretamente no hardware de uma CPU real. A maioria dos emuladores provavelmente nunca simulará esse comportamento. Se o tamanho do PIQ for zero (alterações no código sempre afetam o estado do processador imediatamente), pode-se deduzir que o código está sendo executado em um emulador ou o processador invalida o PIQ ao gravar em endereços carregados no PIQ .

Avaliação de desempenho com base na teoria das filas

Foi AK Erlang (1878-1929) quem primeiro concebeu uma fila como uma solução para o congestionamento no tráfego telefônico. Diferentes modelos de filas são propostos para simular aproximadamente os sistemas de filas em tempo real para que possam ser analisados ​​matematicamente para diferentes especificações de desempenho.

Modelos de enfileiramento podem ser representados usando a notação de Kendall :

A1 / A2 / A3 / A4

Onde:

  • A1 é a distribuição de tempo entre duas chegadas
  • A2 é a distribuição do tempo de serviço
  • A3 é o número total de servidores
  • A4 é a capacidade do sistema
  1. Modelo M / M / 1 (Servidor Único de Fila Única / Markoviano ): Neste modelo, os elementos da fila são atendidos por ordem de chegada. Dadas as taxas médias de chegada e serviço, as taxas reais variam em torno desses valores médios aleatoriamente e, portanto, devem ser determinadas usando uma função de distribuição de probabilidade cumulativa .
  2. Modelo M / M / r : Este modelo é uma generalização do modelo M / M / 1 básico em que vários servidores operam em paralelo. Esse tipo de modelo também pode modelar cenários com usuários impacientes que deixam a fila imediatamente se não estiverem recebendo serviço. Isso também pode ser modelado usando um processo de Bernoulli com apenas dois estados, sucesso e falha. O melhor exemplo desse modelo são nossos sistemas regulares de telefonia fixa.
  3. Modelo M / G / 1 ( modelo de entrada finita de Takacs): Este modelo é usado para analisar casos avançados. Aqui, a distribuição do tempo de serviço não é mais um processo de Markov . Este modelo considera o caso de mais de uma máquina com falha sendo reparada por um único reparador. O tempo de serviço para qualquer usuário vai aumentar neste caso.

Geralmente em aplicativos como fila de entrada de pré-busca, o modelo M / M / 1 é popularmente usado devido ao uso limitado de recursos de fila. Neste modelo de acordo com microprocessadores, o usuário assume o papel de unidade de execução e o servidor é a unidade de interface de barramento.

Fila de instrução

O processador executa um programa obtendo as instruções da memória e executando-as. Normalmente, a velocidade de execução do processador é muito mais rápida do que a velocidade de acesso à memória. A fila de instruções é usada para pré-buscar as próximas instruções em um buffer separado enquanto o processador está executando a instrução atual.

Com um pipeline de quatro estágios , a taxa na qual as instruções são executadas pode ser até quatro vezes maior que a da execução sequencial.

O processador geralmente possui duas unidades separadas para buscar as instruções e para executar as instruções.

A implementação de uma arquitetura de pipeline só é possível se a unidade de interface de barramento e a unidade de execução forem independentes. Enquanto a unidade de execução está decodificando ou executando uma instrução que não requer o uso de barramentos de dados e endereços , a unidade de interface de barramento busca opcodes de instrução da memória.

Este processo é muito mais rápido do que enviar um endereço, ler o opcode e então decodificá-lo e executá-lo. Buscar a próxima instrução enquanto a instrução atual está sendo decodificada ou executada é chamado de pipelining.

A arquitetura 8086 tem um pipeline de instrução de pré-busca de seis bytes, enquanto a 8088 tem uma pré-busca de quatro bytes. Enquanto a Unidade de Execução está executando a instrução atual, a unidade de interface de barramento lê até seis (ou quatro) bytes de opcodes antecipadamente da memória. Os comprimentos da fila foram escolhidos com base em estudos de simulação.

Uma exceção é encontrado quando a unidade de execução encontra um ramo ou seja, a instrução seja um salto ou uma instrução de chamada. Nesse caso, toda a fila deve ser despejada e o conteúdo apontado pelo ponteiro de instrução deve ser obtido da memória.

Inconvenientes

Os processadores que implementam o algoritmo de pré-busca da fila de instruções são bastante avançados do ponto de vista técnico. A complexidade do nível de design da CPU de tais processadores é muito maior do que para processadores regulares. Isso se deve principalmente à necessidade de implementar duas unidades separadas, a BIU e a UE , operando separadamente.

Conforme a complexidade desses chips aumenta, o custo também aumenta. Esses processadores são relativamente mais caros do que seus equivalentes sem a fila de entrada de pré-busca.

No entanto, essas desvantagens são amplamente compensadas pela melhoria no tempo de execução do processador. Após a introdução da fila de instrução de pré-busca no processador 8086, todos os processadores sucessivos incorporaram esse recurso.

código de exemplo x86

code_starts_here:
  mov bx, ahead
  mov word ptr cs:[bx], 9090h
ahead:
  jmp near to_the_end
  ; Some other code
to_the_end:

Este programa de auto-modificação substituirá o jmp to_the_end com dois NOPs (que é codificado como 0x9090 ). O jmp de salto próximo a to_the_end é montado em dois bytes de código de máquina, então os dois NOPs irão apenas sobrescrever este salto e nada mais. (Ou seja, o salto é substituído por um código de não fazer nada.)

Como o código de máquina do salto já foi lido no PIQ e provavelmente também já foi executado pelo processador (processadores superescalares executam várias instruções ao mesmo tempo, mas "fingem" que não, devido à necessidade de compatibilidade com versões anteriores ), a mudança do código não acarretará em nenhuma alteração do fluxo de execução.

Programa de exemplo para detectar o tamanho

Este é um exemplo de NASM - sintaxe auto-modificadora x86 - algoritmo de linguagem assembly que determina o tamanho do PIQ:

code_starts_here:
  xor bx, bx                  ; zero register bx
  xor ax, ax                  ; zero register ax

  mov dx, cs
  mov [code_segment], dx      ; "calculate" codeseg in the far jump below (edx here too)

around:
  cmp ax, 1                   ; check if ax has been altered
  je found_size
                              ; 0x90 = opcode "nop" (NO oPeration)
  mov byte [nop_field+bx], 0x90
  inc bx

  db 0xEA                     ; 0xEA = opcode "far jump"
  dw flush_queue              ; should be followed by offset (rm = "dw", pm = "dd")
code_segment:
  dw 0                        ; and then the code segment (calculated above)
flush_queue:
                              ; 0x40 = opcode "inc ax" (INCrease ax)
  mov byte [nop_field+bx], 0x40
nop_field:
  times 256 nop 
  jmp around
found_size:
  ;
  ;    register bx now contains the size of the PIQ
  ;    this code is for [[real mode]] and [[16-bit protected mode]], but it could easily be changed into
  ;    running for [[32-bit protected mode]] as well. just change the "dw" for
  ;    the offset to "dd". you need also change dx to edx at the top as
  ;    well. (dw and dx = 16 bit addressing, dd and edx = 32 bit addressing)
  ;

O que esse código faz é basicamente alterar o fluxo de execução e determinar por força bruta o tamanho do PIQ. "A que distância devo alterar o código à minha frente para que ele me afete?" Se estiver muito próximo (já está no PIQ), a atualização não terá nenhum efeito. Se estiver longe o suficiente, a mudança do código afetará o programa e o programa então encontrou o tamanho do PIQ do processador. Se este código estiver sendo executado no sistema operacional multitarefa, a troca de contexto pode levar ao valor errado.

Referências

links externos