Giriş kuyruğunu önceden getir - Prefetch input queue

Komut işlem kodlarının program belleğinden önceden alınması, önceden getirme olarak bilinir ve önceden getirme girdi kuyruğu (PIQ) kullanılarak sunulur . Önceden getirilen komutlar veri yapısında, yani bir kuyrukta saklanır . İşlem kodlarının, yürütme gereksinimlerinden önce çok önceden alınması, işlemcinin hızını artırarak genel verimliliğini artırır . İşlemci, sonraki talimat işlem kodunun tamamlanması için artık bellek erişim işlemlerini beklemek zorunda değildir. Bu mimari, Intel 8086 mikroişlemcisinde belirgin bir şekilde kullanılmıştır .

Tanıtım

Daha hızlı ve daha verimli bilgi işlem ihtiyacı nedeniyle, 1960'larda bilgi işlem mimarisi tasarımında boru hattı ön plana çıkarıldı. Pipelining daha geniş bir kavramdır ve çoğu modern işlemci, komutlarını çalıştırmadan önce bazı saat döngüleri yükler . Bu, makine kodunu bellekten önceden getirme giriş kuyruğuna önceden yükleyerek elde edilir .

Bu davranış yalnızca , kendi kendini değiştiren kod çalıştırabilen ve bir tür talimat ardışık düzenine sahip olan von Neumann bilgisayarları (yani Harvard mimarisi bilgisayarları değil ) için geçerlidir . Neredeyse tüm modern yüksek performanslı bilgisayarlar bu üç gereksinimi karşılar.

Genellikle, PIQ'nun önceden getirme davranışı CPU'nun programlama modeli tarafından görülmez . Ancak, PIQ davranışının görünür olduğu ve programcı tarafından dikkate alınması gereken bazı durumlar vardır.

Ne zaman x86 dan modunu değiştirir -İşlemci realmode için korumalı mod tersi ve yardımcısı, PIQ sahiptir temizlenip, yoksa işlemci çevirmek devam edecektir makine kodu onun son modda yazılmış gibi. PIQ temizlenmemişse, işlemci kodlarını yanlış çevirebilir ve geçersiz bir talimat istisnası oluşturabilir .

Kendi kendini değiştiren kod yürütülürken , geçerli yürütme konumunun hemen önündeki işlemci kodunda bir değişiklik, zaten PIQ'suna yüklendiğinden, işlemcinin kodu nasıl yorumladığını değiştirmeyebilir. Kodun RAM ve/veya önbelleğindeki yeni ve değiştirilmiş sürümü yerine, PIQ'da önceden yüklenmiş olan eski kopyasını yürütür .

PIQ'nun bu davranışı, kodun bir öykünücünün içinde mi yoksa doğrudan gerçek bir CPU'nun donanımında mı yürütüldüğünü belirlemek için kullanılabilir . Çoğu öykünücü muhtemelen bu davranışı hiçbir zaman simüle etmeyecektir . PIQ boyutu sıfırsa (koddaki değişiklikler her zaman işlemcinin durumunu hemen etkiler), kodun bir öykünücüde yürütüldüğü veya işlemcinin PIQ'ya yüklenen adreslere yazma üzerine PIQ'yu geçersiz kıldığı sonucuna varılabilir. .

Kuyruk teorisine dayalı performans değerlendirmesi

Öyleydi AK Erlang ilk telefon trafiğinde tıkanıklık bir çözüm olarak bir sıranın tasavvur (1878-1929). Farklı performans özellikleri için matematiksel olarak analiz edilebilmesi için gerçek zamanlı kuyruk sistemlerini yaklaşık olarak simüle etmek için farklı kuyruk modelleri önerilmiştir.

Kuyruk modelleri Kendall'ın notasyonu kullanılarak temsil edilebilir :

A1/A2/A3/A4

nerede:

  • A1, iki varış arasındaki zamanın dağılımıdır
  • A2 hizmet süresi dağılımıdır
  • A3 toplam sunucu sayısıdır
  • A4 sistemin kapasitesidir
  1. M/M/1 Modeli (Single Queue Single Server/ Markovian ): Bu modelde, kuyruk elemanları ilk gelen ilk alır esasına göre sunulur. Ortalama varış ve hizmet oranları göz önüne alındığında, gerçek oranlar bu ortalama değerler etrafında rastgele değişir ve dolayısıyla kümülatif bir olasılık dağılım fonksiyonu kullanılarak belirlenmelidir .
  2. M/M/r Modeli : Bu model, birden çok sunucunun paralel olarak çalıştığı temel M/M/1 modelinin genelleştirilmiş halidir. Bu tür bir model, hizmet alamadıklarında hemen kuyruktan ayrılan sabırsız kullanıcıların olduğu senaryoları da modelleyebilir. Bu aynı zamanda sadece iki durumu, başarı ve başarısızlık olan bir Bernoulli süreci kullanılarak modellenebilir . Bu modelin en iyi örneği, normal sabit hatlı telefon sistemlerimizdir.
  3. M/G/1 Modeli (Takacs'ın sonlu girdi Modeli) : Bu model, gelişmiş durumları analiz etmek için kullanılır. Burada hizmet süresi dağılımı artık bir Markov süreci değildir . Bu model, birden fazla arızalı makinenin tek bir tamirci tarafından onarılması durumunu ele alır. Bu durumda herhangi bir kullanıcı için hizmet süresi artacaktır.

Genellikle giriş kuyruğunu önceden getir gibi uygulamalarda, kuyruk özelliklerinin sınırlı kullanımı nedeniyle M/M/1 Modeli yaygın olarak kullanılmaktadır. Bu modelde mikroişlemcilere uygun olarak kullanıcı yürütme birimi rolünü üstlenir ve sunucu bus arayüz birimidir.

talimat kuyruğu

İşlemci, talimatları bellekten alıp yürüterek bir programı yürütür. Genellikle işlemci yürütme hızı, bellek erişim hızından çok daha hızlıdır. Komut kuyruğu, işlemci mevcut talimatı yürütürken sonraki talimatları ayrı bir arabellekte önceden getirmek için kullanılır.

Bir ile dört aşamalı boru hattı , komutların olan oranı bu ardışık uygulamalar dört kata kadar olabilir.

İşlemci genellikle talimatları almak ve talimatları yürütmek için iki ayrı birime sahiptir.

Bir boru hattı mimarisinin uygulanması, yalnızca veri yolu arabirim birimi ve yürütme birimi bağımsız olduğunda mümkündür. Yürütme birimi, veri ve adres yollarının kullanılmasını gerektirmeyen bir komutun kodunu çözerken veya yürütürken, veri yolu arabirim birimi bellekten talimat işlem kodlarını getirir .

Bu işlem, bir adres göndermekten, işlem kodunu okumaktan ve ardından kodunu çözmekten ve yürütmekten çok daha hızlıdır. Mevcut talimatın kodu çözülürken veya yürütülürken bir sonraki talimatın getirilmesine ardışık düzen denir.

8086 ise mimari, altı bayt önceden getirme talimatı boru hattı vardır 8088 dört baytlık ön alma vardır. Yürütme Birimi mevcut talimatı yürütürken, veri yolu arabirim birimi bellekten önceden altı (veya dört) bayta kadar işlem kodu okur. Kuyruk uzunlukları simülasyon çalışmalarına göre seçilmiştir.

Yürütme birimi bir dal talimatıyla, yani bir atlama veya bir çağrı talimatıyla karşılaştığında bir istisna ile karşılaşılır . Bu durumda, tüm kuyruğun boşaltılması ve talimat işaretçisinin işaret ettiği içeriğin bellekten alınması gerekir.

Dezavantajları

Talimat kuyruğu önceden getirme algoritmasını uygulayan işlemciler teknik olarak oldukça ileri düzeydedir. Bu tür işlemcilerin CPU tasarım düzeyi karmaşıklığı, normal işlemcilerden çok daha yüksektir. Bunun temel nedeni, ayrı ayrı çalışan BIU ve EU olmak üzere iki ayrı birimin uygulanması ihtiyacıdır .

Bu yongaların karmaşıklığı arttıkça maliyet de artmaktadır. Bu işlemciler, önceden getirme girdi kuyruğu olmayan emsallerinden nispeten daha maliyetlidir.

Bununla birlikte, bu dezavantajlar, işlemci yürütme süresindeki iyileşme ile büyük ölçüde dengelenmiştir. 8086 işlemcide önceden getirme talimat kuyruğunun tanıtılmasından sonra, ardışık tüm işlemciler bu özelliği dahil etti.

x86 örnek kod

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

Bu kendi kendini değiştiren program, jmp to_the_end'in üzerine iki NOP ( 0x9090 olarak kodlanmıştır ) yazacaktır . to_the_end yakınlarındaki atlama jmp , iki baytlık makine kodunda birleştirilir, bu nedenle iki NOP yalnızca bu atlamanın üzerine yazar ve başka bir şey yapmaz. (Yani, atlama, hiçbir şey yapmama koduyla değiştirilir.)

Atlamanın makine kodu zaten PIQ'da okunduğundan ve muhtemelen işlemci tarafından da yürütüldüğünden ( süperskalar işlemciler aynı anda birkaç talimatı yürütür, ancak geriye dönük uyumluluk ihtiyacı nedeniyle yapmıyormuş gibi yaparlar ), kod değişikliği, yürütme akışında herhangi bir değişikliğe neden olmaz.

Boyutu algılamak için örnek program

Bu, PIQ'nun boyutunu belirleyen örnek bir NASM - sözdizimi kendi kendini değiştiren x86 - montaj dili algoritmasıdır:

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)
  ;

Bu kodun yaptığı şey, temel olarak yürütme akışını değiştirmesi ve PIQ'nun ne kadar büyük olduğunu kaba kuvvetle belirlemesidir . "Beni etkilemesi için önümdeki kodu ne kadar uzakta değiştirmem gerekiyor?" Çok yakınsa (zaten PIQ'dadır) güncellemenin herhangi bir etkisi olmayacaktır. Yeterince uzaksa, kod değişikliği programı etkileyecektir ve program daha sonra işlemcinin PIQ'sunun boyutunu bulmuştur. Bu kod çok görevli işletim sistemi altında yürütülüyorsa, bağlam anahtarı yanlış değere yol açabilir.

Referanslar

Dış bağlantılar