Hent inngangskø på forhånd - Prefetch input queue

Henter instruksjons opcodes fra programminnet godt på forhånd er kjent som forhåndsinnhenting og det blir servert ved hjelp av forhåndshenting inngangskøen (PIQ) sikret forhåndshentet instruksjoner er lagret i datastrukturen - nemlig en . Henting av opcodes i god tid, før de trenger utførelse, øker prosessorens generelle effektivitet og øker hastigheten. Prosessoren trenger ikke lenger å vente på minnetilgangsoperasjonene for at den påfølgende instruksjonskoden skal fullføres. Denne arkitekturen ble fremtredende brukt i Intel 8086 -mikroprosessoren .

Introduksjon

Pipelining ble brakt i spissen for databehandlingsarkitekturdesign i løpet av 1960 -årene på grunn av behovet for raskere og mer effektiv databehandling. Rørledning er det bredere konseptet, og de fleste moderne prosessorer laster instruksjonene noen klokkesykluser før de utfører dem. Dette oppnås ved å forhåndslaste maskinkode fra minnet til en forhåndshentingskø .

Denne oppførselen gjelder bare von Neumann-datamaskiner (det vil si ikke Harvard-arkitekturdatamaskiner ) som kan kjøre selvmodifiserende kode og ha en slags instruksjonsrørledning . Nesten alle moderne datamaskiner med høy ytelse oppfyller disse tre kravene.

Vanligvis er forhåndshenting av PIQ usynlig for programmeringsmodellen til CPUen. Imidlertid er det noen omstendigheter der oppførselen til PIQ er synlig, og må tas i betraktning av programmereren.

Når x86 -prosessoren endrer modus fra realmode til beskyttet modus og omvendt, må PIQ skylles, ellers vil CPU fortsette å oversette maskinkoden som om den ble skrevet i sin siste modus. Hvis PIQ ikke er tømt, kan prosessoren sette sine koder feil og generere en ugyldig instruksjon unntak .

Når du utfører selvmodifiserende kode , kan det hende at en endring i prosessorkoden umiddelbart foran den nåværende plasseringen av utførelsen ikke endrer hvordan prosessoren tolker koden, siden den allerede er lastet inn i PIQ-en. Den utfører ganske enkelt sin gamle kopi som allerede er lastet inn i PIQ i stedet for den nye og endrede versjonen av koden i RAM og/eller cache .

Denne oppførselen til PIQ kan brukes til å avgjøre om kode blir utført inne i en emulator eller direkte på maskinvaren til en ekte CPU. De fleste emulatorer vil sannsynligvis aldri simulere denne oppførselen. Hvis PIQ-størrelsen er null (endringer i koden påvirker alltid prosessortilstanden umiddelbart), kan det utledes at enten koden blir utført i en emulator eller at prosessoren ugyldiggjør PIQ ved skriving til adresser lastet i PIQ .

Ytelseevaluering basert på køteori

Det var AK Erlang (1878-1929) som først tenkte seg en kø som en løsning på overbelastning i telefontrafikk. Ulike kømodeller er foreslått for omtrent å simulere køsystemene i sanntid slik at de kan analyseres matematisk for forskjellige ytelsesspesifikasjoner.

Modeller i kø kan representeres ved hjelp av Kendalls notasjon :

A1/A2/A3/A4

hvor:

  • A1 er fordelingen av tid mellom to ankomster
  • A2 er fordelingen av tjenestetiden
  • A3 er det totale antallet servere
  • A4 er systemets kapasitet
  1. M/M/1-modell (Single Queue Single Server/ Markovian ): I denne modellen blir elementer i kø servert etter førstemann til mølla-prinsippet. Gitt gjennomsnittlig ankomst- og servicepris, varierer de faktiske prisene tilfeldig rundt disse gjennomsnittsverdiene, og må derfor bestemmes ved hjelp av en kumulativ sannsynlighetsfordelingsfunksjon .
  2. M/M/r -modell : Denne modellen er en generalisering av den grunnleggende M/M/1 -modellen der flere servere opererer parallelt. Denne typen modeller kan også modellere scenarier med utålmodige brukere som forlater køen umiddelbart hvis de ikke mottar service. Dette kan også modelleres ved hjelp av en Bernoulli -prosess som bare har to stater, suksess og fiasko. Det beste eksemplet på denne modellen er våre vanlige fasttelefonsystemer.
  3. M/G/1 -modell (Takacs endelige inngangsmodell): Denne modellen brukes til å analysere avanserte saker. Her er tjenestetidsfordelingen ikke lenger en Markov -prosess . Denne modellen vurderer tilfellet med mer enn en feilaktig maskin som ble reparert av en enkelt reparatør. Servicetiden for enhver bruker kommer til å øke i dette tilfellet.

Vanligvis i applikasjoner som prefetch -inngangskø, brukes M/M/1 -modellen populært på grunn av begrenset bruk av køfunksjoner. I denne modellen, i samsvar med mikroprosessorer, tar brukeren rollen som utføringsenheten, og serveren er bussgrensesnittenheten.

Instruksjonskø

Prosessoren kjører et program ved å hente instruksjonene fra minnet og utføre dem. Vanligvis er prosessorkjøringshastigheten mye raskere enn minnetilgangshastigheten. Instruksjonskø brukes til å forhåndshente de neste instruksjonene i en egen buffer mens prosessoren utfører den nåværende instruksjonen.

Med en firetrinns rørledning kan hastigheten som instruksjoner utføres på være opptil fire ganger så høy som sekvensiell kjøring.

Prosessoren har vanligvis to separate enheter for å hente instruksjonene og for å utføre instruksjonene.

Implementering av en rørledningarkitektur er bare mulig hvis bussgrensesnittenheten og utførelsesenheten er uavhengige. Mens utføringsenheten dekoder eller utfører en instruksjon som ikke krever bruk av data- og adressebussene , henter bussgrensesnittenheten instruksjonskoder fra minnet.

Denne prosessen er mye raskere enn å sende ut en adresse, lese opcode og deretter dekode og utføre den. Å hente den neste instruksjonen mens den nåværende instruksjonen blir dekodet eller utført kalles pipelining.

Den 8086 arkitektur har en seks-byte prefetch instruksjon rørledning, mens 8088 har en fire-byte forhåndshenting. Når eksekveringsenheten utfører den nåværende instruksjonen, leser bussgrensesnittenheten opptil seks (eller fire) byte med opkoder på forhånd fra minnet. Kølengdene ble valgt basert på simuleringsstudier.

Et unntak oppstår når utførelsesenheten støter på en greninstruksjon , dvs. enten et hopp eller en anropsinstruksjon. I dette tilfellet må hele køen dumpes og innholdet som instruksjonspekeren viser til må hentes fra minnet.

Ulemper

Prosessorer som implementerer algoritmen for forhåndshenting av instruksjonskø er ganske teknisk avanserte. Den CPU utformingen nivå kompleksiteten i slike prosessorer er mye høyere enn for vanlige prosessorer. Dette er først og fremst på grunn av behovet for å implementere to separate enheter, BIU og EU , som opererer separat.

Etter hvert som kompleksiteten til disse sjetongene øker, øker også kostnaden. Disse prosessorene er relativt dyrere enn sine kolleger uten forhåndshentingskøen.

Imidlertid oppveies disse ulempene sterkt av forbedringen i prosessorkjøringstiden. Etter introduksjonen av prefetch -instruksjonskø i 8086 -prosessoren har alle påfølgende prosessorer innarbeidet denne funksjonen.

x86 eksempelkode

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

Dette selvmodifiserende programmet vil overskrive jmp to_the_end med to NOP-er (som er kodet som 0x9090 ). Hoppet jmp nær to_the_end er satt sammen til to byte maskinkode, så de to NOPene vil bare overskrive dette hoppet og ingenting annet. (Det vil si at hoppet er erstattet med en gjør-ingenting-kode.)

Fordi maskinens kode for hoppet allerede er lest inn i PIQ, og sannsynligvis også allerede utført av prosessoren ( superkalare prosessorer utfører flere instruksjoner samtidig, men de "later som" at de ikke gjør det på grunn av behovet for bakoverkompatibilitet ), endringen av koden vil ikke ha noen endring i utførelsesflyten.

Eksempelprogram for å oppdage størrelse

Dette er et eksempel NASM - syntaks selvmodifiserende x86 - samlingsspråklalgoritme som bestemmer størrelsen på 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)
  ;

Hva denne koden gjør er i utgangspunktet at den endrer utførelsesflyten, og bestemmer med brute force hvor stor PIQ er. "Hvor langt unna må jeg endre koden foran meg for at den skal påvirke meg?" Hvis den er for nær (den er allerede i PIQ) vil oppdateringen ikke ha noen effekt. Hvis det er langt nok, vil endringen av koden påvirke programmet, og programmet har da funnet størrelsen på prosessorens PIQ. Hvis denne koden utføres under multitasking OS, kan kontekstbryteren føre til feil verdi.

Referanser

Eksterne linker