Wednesday 4 October 2017

Future Implementation of VLIW

Sebuah implementasi VLIW akan menghasilkan efek yang sama dengan superscalar RISC atau implementasi CISC, tapi desain VLIW melakukannya tanpa dua bagian yang paling kompleks dari desain superscalar berperforma tinggi.

Karena instruksi VLIW
secara eksplisit menentukan beberapa operasi independen yang secara eksplisit menentukan paralelisme, maka tidak diperlukan untuk melakukan decoding dan pengiriman hardware untuk merekonstruksi paralelisme dari aliran instruksi serial. Alih-alih berupaya untuk menemukan paralelisme, prosesor VLIW hanya akan mengandalkan compiler penghasil kode VLIW untuk secara eksplisit menentukan paralelisme. Mengandalkan kompilator memiliki kelebihan.

Pertama, compiler memiliki kemampuan untuk melihat instruksi dari jendela yang jauh lebih besar dari daripada perangkat keras. Untuk prosesor superscalar, jendela hardware yang lebih besar berdampak pada jumlah yang lebih besar dari logika dan area chip.

Pada beberapa titik, ada yang tidak cukup baik sehingga ukuran jendela dibatasi. Lebih buruk lagi, bahkan sebelum batas sederhana pada jumlah hardware tercapai, kompleksitas dapat berpengaruh pada kecepatan logika, sehingga ukuran jendela dibatasi untuk menghindari berkurangnya kecepatan clock chip. Jendela software dapat menjadi besar. Dengan demikian, mencari paralelisme di jendela perangkat lunak mungkin untuk memperoleh hasil yang lebih baik.

Kedua, compiler memperoleh pengetahuan dari kode sumber program. Source code biasanya berisi informasi penting tentang perilaku program yang dapat digunakan untuk membantu paralelisme maksimum untuk diungkapkan pada tingkat instruksi-set. Sebuah teknik yang kuat yang disebut jejak-driven kompilasi dapat digunakan untuk meningkatkan kualitas output kode kompilator secara dramatis. Jejak-drive kompilasi pertama menghasilkan sebuah program VLIW yang belum optimal, tapi benar. Program ini telah menanamkan rutinitas yang mencatat perilaku program. Catatan perilaku program yang diambil, seperti berapa percabangan yang diambil dan seberapa sering, digunakan oleh compiler selama kompilasi kedua untuk menghasilkan kode yang mengambil manfaat dari informasi yang akurat tentang perilaku program. Dengan memiliki jejak-arah kompilasi, compiler memiliki akses ke beberapa informasi dinamis yang akan mempermudah logika pengiriman hardware dalam prosesor superscalar.

Ketiga, dengan register yang memadai dapat ditiru fungsi implementasi superscalar reorder buffer. Tujuan dari buffer menyusun ulang adalah untuk memungkinkan prosesor superscalar untuk mengeksekusi instruksi spekulatif dan kemudian dapat dengan cepat membuang hasil spekulatif jika perlu. Dengan register yang cukup, mesin VLIW dapat menempatkan hasil instruksi spekulatif yang dieksekusi pada register sementara.

Compiler
mengetahui berapa banyak instruksi yang akan dieksekusi secara spekulatif, sehingga hanya akan menggunakan register dengan berspekulasi sepanjang jalur (yang diprediksi) dan mengabaikan nilai-nilai pada register tersebut di sepanjang jalur yang akan diambil jika percabangan tersebut ternyata telah salah memprediksi.


Gambar dibawah ini menunjukkan implementasi VLIW
secara umum, tanpa reorder buffer yang kompleks serta pengiriman logika.

Implementasi VLIW Secara Umum





Bagaimana VLIW Bekerja

Arsitektur VLIW merupakan solusi sebaliknya dari superscalar. Dimana arsitektur ini akan mereduksi beberapa penggunaan hardware yang kompleks seperti Instruction Windows untuk mendeteksi paralelisme.
Dengan tidak adanya Instruction Windows apakah arsitektur VLIW masih mampu melakukan prediksi paralelisme?
Jawabannya adalah YA. Tidak seperti halnya pada arskitektur superscalar yang memprediksi paralelisme pada saat run-time program yaitu dengan memasukkan setiap instruksi dan juga prediksi percabangan (branch prediction) kedalam instruction windows kemudian baru diprediksi paralelismenya, arsitektur VLIW justru memprediksinya pada saat compile-time. Program secara keseluruhan oleh compiler akan memprediksi operasi yang dapat diparalelkan kemudian operasi tersebut akan dikelompokkan masing-masing kedalam sebuah instruksi yang “sangat besar” (instruksi inilah yang kita sebut dengan Very Large Instruction Word) yang memiliki panjang tetap. Kemudian instruksi yang tergabung ini akan dieksekusi secara parallel.
Catatan: arsitektur VLIW sangat bergantung pada kapabilitas Compiler!
Teknik compiler guna menambah potensi paralelisme antara lain:
è Loop Unrolling
è Trace Schedulling


A.   Loop Unrolling

Loop unrolling merupakan teknik yang dilakukan oleh compiler untuk meningkatkan potensi paralelisme, yaitu dengan cara menuliskan statement didalam loop beberapa kali.
for(i=959;i>=0;i--)
{
   x[i] = x[i]+s;
}
CONTOH: #PENJUMLAHAN FLOATING POINT SKALAR KEDALAM FLOATING POINT VEKTOR



Program tersebut akan dikompilasi menjadi:
-asumsikan bahwa register R1 telah menyimpan alamat elemen terakhir x, dan elemen lainnya disimpan pada alamat dibawahnya secara berurut, sehingga x[0] berada pada alamat 0.
Loop:   LDD     F0, (R1)           F0 <- x[i] ;(load double)
            ADF     F4,F0,F2         F4 <- F0 + F2 ;(floating pnt)
            STD     (R1),F4            x[i] <- F4 ;(store double)
            SBI      R1,R1,#8         R1 <- R1 - 8
            BGEZ R1,Loop

CYCLE TIME TABLE
Hasilnya:
- 1 iterasi = 6cycle
- total iterasi = 960*6 = 5760cycle
ASUMSI: Prosesor VLIW yang digunakan memiliki rule dimana 1 clock cycle dapat dilakukan 2 operasi memory reference, 2 operasi floating point, dan 1 operasi integer/percabangan. Dimana untuk proses load untuk double-word (DW), member tambahan 1 cycle dan operasi floating point member tambahan 2 cycle.
Dengan teknik loop unrolling, kode tersebut dapat ditulis ulang menjadi:
for(i=959;i>=0;i-=2)
{
   x[i] = x[i]+s;
   x[i-1] = x[i-1]+s;
}
 



Kompilasi kode:
Loop: LDD       F0, (R1)           F0 <- x[i] ;(load double)
            ADF     F4,F0,F2         F4 <- F0 + F2 ;(floating pnt)
            STD     (R1),F4            x[i] <- F4 ;(store double)
            LDD     F0, -8(R1)       F0 <- x[i-1] ;(load double)
            ADF     F4,F0,F2         F4 <- F0 + F2 ;(floating pnt)
            STD     -8(R1),F4        x[i-1] <- F4 ;(store double)
            SBI      R1,R1,#16       R1 <- R1 - 16
            BGEZ R1,Loop

CYCLE TIME TABLE
Hasilnya:
- 2 iterasi = 6cycle
- total iterasi = (960/2)*6 = 2880cycle
Begitu seterusnya, sehingga dengan melakukan loop unrolling akan meningkatkan paralelisme dan memperkecil kebutuhan cycle time. Namun teknik loop unrolling juga memiliki batasan, karena dengan menambah unroll maka akan membuat program menjadi bertambah besar dan berimbas pada bertambahnya kebutuhan memori untuk menyimpan program tersebut, juga semakin banyak unroll yang dilakukan akan menambah jumlah register yang dibutuhkan sehingga akan meningkatkan traffic pada pengaksesan register.



Trace Scheduling

Trace scheduling merupakan teknik lain yang dilakukan untuk mengoptimalkan paralelisme. Teknik ini dilakukan pada operasi percabangan.
Program secara umum dapat dideskripsikan melalui sebuah graf, dimana setiap node menunjukkan operasi (atau sering disebut dengan program flow graph). Trace merupakan jalur nonsiklik yang melalui graf tersebut. Tujuan utama trace scheduling adalah untuk mencari trace yang paling optimal.
Trace scheduling terdiri dari 3 tahapan, yaitu:
-          Pemilihan Trace (Trace Selection)
-          Instruction Scheduling
-          Compensation and Replacement

a.    Trace Selection
Dalam tahapan ini dipilih jalur yang paling sering dieksekusi / dilalui.
Contoh program:
if(c!=0)
{
b = a / c;
}
else
{
b = 0; h=0;
}
f = g + h;


Maka, hasil kompilasi program menjadi:
LD       R0, c               R0 <- c ;(load word)
                  BZ       R0,Else
                  LD       R1, a               R1 <- a ;(load integer)
                  DV       R1,R1,R0        R1 <- R1 / R0 ;(integer)
                  ST       b,R1                b <- R1 ;(store word)
                  BR       Next
Else:         STI      b,#0                 b <- 0
                  STI      h,#0                 h - 0
Next:         LD       R0, g               R0 <- g ;(load word)
                  LD       R1, h               R1 <- h ;(load word)
                  AD       R1,R1,R0        R1 <- R1 + R0 ;(integer)
                  ST       f,R1                 f <- R1 ;(store word)
EndIF: - - - - - - - - - - - - - - -

Representasi node:
INSTRUKSI
NODE
INSTRUKSI
NODE
LD R0,c
A
STI h,#0
G
BZ R0,Else
B
LD R0,g
H
LD R1,a
C
LD R1,h
I
DV R1,R1,R0
D
AD R1,R1,R0
J
ST b,R1
E
ST f,R1
K
STI b,#0
F




b.    Instruction Scheduling
Pada tahap ini trace yang telah dipilih akan dijadwalkan kedalam operasi parallel pada prosesor VLIW.

c.    Replacement and Compensation
Pada tahap ini, compensation code ditambahkan bertujuan untuk menjaga agar program tetap konsisten/benar.

Contoh kondisi yang membutuhkan compensation code:
-           - Pada cycle kedua, proses load nilai g dan h dilakukan sebelum kondisi percabangan.
-           - Pada cycle pertama, proses load nilai a juga dilakukan sebelum kondisi percabangan.
-         - Pada cycle keempat, proses store nilai pada b setelah proses percabangan (berada pada  bagian next)

Solusinya adalah dengan menambahkan kode else dan compensation code:
CATATAN: ditambahkan compensation code (tambahan kode) karena, R3 meng-load nilai h sebelum percabangan sehingga agar nilai yg didapat tetap benar maka pada Register R3 diisi dengan nilai 0 (sesuai kondisi Else dimana h=0).




Intel Itanium Processor

Itanium-1 prosesor 64-bit, memiliki 6 keluaran dari VLIWprocessor dengan empat unit integer, empat unit multimedia, dua load / store unit, dua unit presisi floating point yang diperpanjang dan dua unit single floating point presisi. Arsitektur Intel Itenium ditunjukkan pada Gambar dibawah ini. 

Arsitektur Intel Itanium

Prosesor ini berjalan pada processor 800 MHz dengan proses 0,18 mikron dan memiliki pipa 10 tahap. Setiap MultiOp terdiri dari satu atau lebih 128 bit bundel. Setiap 128 bit bundel tersebut terdiri dari tiga operasi dan contoh. Contoh meng-encode kombinasi umum dari jenis-jenis operasi. Karena bidang template hanya memiliki lebar 5 bit, bundel tidak mendukung semua kemungkinan kombinasi jenis instruksi. Ada 128 register tujuan umum dan satu set lainnya dari 128, 82-bit floating point register berukuran lebar. Gambaran format instruksi ditunjukkan pada Gambar dibawah ini.

Format Instuksi Intel Itanium


Modul penjadwalan adalah teknik pipelining  pada software yang dapat mendukung tumpang tindih dari eksekusi loop untuk mengurangi ekor” dari kode. Dalam sebuah unit pipeline, setiap tahap memegang perhitungan dan setiap unit data dapat diterapkan untuk fungsi unit sebelumnya dimana data tersebut telah benar-benar diproses. Untuk mengambil keuntungan dari operasi pipeline, dalam sebuah modul loop, loop akan terbuka dan dibagi menjadi beberapa tahap. Compiler dapat menjadwalkan beberapa iterasi dari sebuah loop secara pipeline asalkan data output dari satu tahap mengalir masuk ke tahap berikutnya dalam pipa software. Secara tradisional, ini pembukaan loop ini memerlukan penggantian nama register dalam iterasi berturut-turut.

Untuk mendukung spekulasi data, processor mendukung jenis khusus dari beban yang disebut advance load. Jika compiler tidak dapat enghubungkan  antara alamat toko dan beban kemudian, dapat mengeluarkan beban muka depan toko. Prosesor menggunakan struktur hardware khusus yang disebut ALAT untuk melacak apakah sebuah toko kemudian menulis ke lokasi yang sama dengan beban muka.

Pada lokasi asli di mana beban telah secara alami ditempatkan, compiler menyisipkan operasi pemeriksaan khusus untuk melihat apakah sebuah penyimpanan membatalkan hasil dari beban. Jika beban muka tidak disahkan, dilakukan operasi pemeriksaan untuk mengontrol transfer ke kode pemulihan.

Hal ini mendukung kedua petunjuk statis dan dinamis dari percabangan serta penggunaan hardware untuk memprediksi percabangan. Ada juga petunjuk dalam instruksi beban dan penyimpanan yang menginformasikan prosesor tentang perilaku cache pada operasi memori tertentu.



Intel Itanium 2 Processor

Prosesor Intel Itanium 2 adalah implementasi kedua dari Itanium Instruction Set Architecture (ISA). Prosesor Itanium 2 terdiri dari 6-wide, 8-stage deep pipeline yang berjalan antara 1.0 GHz atau 900MHz. Terdiri dari 6 unit integer, 6 unit multimedia, dua unit load dan store, 3 unit branch, dua unit extended-precision floating-point, dua tambahan unit single-precision floating-point. Hardwarenya tediri dari dynamic prefetch, branch prediction, sebuah scoreboard register, dan non-blocking cache. Tiga level on-die cache, L1, L2, L3 untuk meminimalisir latensi memori secara keseluruhan. Teridiri dari 3 MB atau 1,5 MB L3 cache, dengan data bandwidth 32 GB/cycle. System bus didesain untuk glueless MP support hingga 4 processor per system bus, dan dapat digunakan sebagai building block yang efektif untuk sistem yang berskala besar. Arsitektur Intel Itanium 2 dapat dilihat pada Gambar dibawah ini.
Arsitektur Prosesor Intel Itanium 2





Keuntungan dari Kompleksitas Compiler atas Kompleksitas Hardware

Ketika arsitektur VLIW mengurangi kompleksitas hardware selama implementasi superscalar, compiler yang jauh lebih kompleks tetap diperlukan. Pengembangan implementasi dari kinerja maksimum pada superscalar RISC atau CISC tidak memperoleh teknik compiler yang canggih, tetapi tingkat kecanggihan dalam compiler VLIW secara signifikan lebih tinggi.


VLIW hanya bergerak secara kompleks dari perangkat keras ke perangkat lunak. Trade-off ini memiliki sisi manfaat yang signifikan: kompleksitas hanya dilakukan sekali, ketika compiler tidak ditulis setiap kali chip ini dipabrikasi. Diantara manfaatnya adalah diperoleh sebuah chip yang lebih kecil sehingga meningkatkan keuntungan bagi vendor mikroprosesor dan harga yang lebih murah bagi pelanggan yang menggunakannya. Kompleksitas biasanya lebih mudah ditangani dalam desain perangkat lunak dari pada hardware. Dengan demikian, akan lebih sedikit biaya untuk merancang, lebih cepat untuk mendesain, dan lebih sedikit memerlukan debugging. Semua itu adalah faktor-faktor yang dapat membuat desain mikroprossor menjadi lebih murah. Selain itu, perbaikan compiler dapat dilakukan setelah chip telah dibuat. Sementara perbaikan pada hardware superscalar memerlukan perubahan pada mikroprosesor, yang secara alami akan menimbulkan biaya besar untuk mengubah desain chip.



Implementasi Arsitektur VLIW

Format instruksi VLIW yang paling sederhana mengkodekan operasi untuk setiap unit eksekusi pada mesin. Hal ini wajar dengan asumsi setiap instruksi akan selalu memiliki sesuatu yang berguna untuk melakukan setiap eksekusi. Namun, meskipun dengan algoritma compiler yang terbaik, biasanya tidak mungkin untuk mengirimkan setiap instruksi ke semua unit eksekusi. Selain itu, pada mesin VLIW  yang memiliki unit eksekusi integer dan floating-point, compiler terbaik tidak akan mampu untuk menjaga unit floating point selalu sibuk selama pelaksanaan aplikasi integer.

Masalah dengan instruksi
seperti itu tidak membuat penuh penggunaan semua unit eksekusi sehingga membuang sumber daya processor: instruksi ruang memori, ruang instruksi cache, dan bandwidth bus.

Setidaknya ada dua solusi untuk mengurangi pemborosan sumber daya karena instruksi yang jarang. Pertama, instruksi dapat dikompresi dengan representasi yang sangat-encoded. Sejumlah teknik, seperti kode Huffman dapat digunakan untuk mengalokasikan bit yang paling sedikit pada operasi yang paling sering digunakan.

Kedua,
kemungkinan untuk mendefinisikan kata instruksi dengan mengkode lebih sedikit operasi dibandingkan jumlah eksekusi yang tersedia. Bayangkan mesin VLIW dengan sepuluh eksekusi tapi instruksinya hanya dapat menjalankan lima operasi. Dalam skema ini, sejumlah unit dikodekan bersamaan dengan operasi dan menentukan unit eksekusi mana yang seharusnya dikirimkan. Manfaatnya adalah pada penggunaan sumber daya yang lebih baik. Masalah potensialnya adalah instruksi yang pendek membatasi mesin dalam mengerjakan jumlah maksimum operasi pada satu waktu. Untuk mencegah masalah pembatasan kinerja ini, ukuran dari kata instruksi dapat disesuaikan berdasarkan analisis simulasi atau perilaku program.

Tentu saja,
sangat mungkin untuk menggabungkan teknik lainnya: menggunakan kompresi yang lebih pendek dari panjang instruksi maksimum.


Conclusion:
  1.    Implementasi VLIW highly parallel lebih sederhana dan lebih murah dibandingkan yang sejenisnya yaitu RISC dan CISC;
  2.    Encoding dari VLIW word melibatkan paralelisme terhadap instruksi primitif, yang dapat mengurangi hardware complexity seperti pada arsitektur superscalar;
  3.      Compiler harus menggabungkan beberapa instruksi primitif menjadi sebuah VLIW word, untuk memastikan semua function unit tidak idle;
  4.     Compiler melakukan optimasi pipeline secara software, dengan melakukan re-ordering untuk mecapai tingkat paralelisme tertinggi dalam sequential code;
  5.       Kinerja Microprosesor tergantung dari bagaimana cara compiler menghasilkan VLIW words.

No comments:

Post a Comment