Bosh sahifa Wiki Loop Fission

Loop Fission

Loop Fission — bitta sikl tanasidagi statementlarni ikki yoki undan ortiq alohida siklga ajratish optimallashtirishi. U loop distribution deb ham ataladi va working setni kichraytirish, vectorizationni ochish yoki mustaqil ishlarni ajratish uchun qo‘llanadi.

Ajratish natijasi

for i { a[i]=f(i); b[i]=g(a[i]); } ikki siklga ajratilganda barcha a elementlari avval hisoblanadi, keyin b yaratiladi. Bu immediate localityni yo‘qotishi mumkin, ammo har yangi body sodda bo‘lib SIMDga mos kelishi yoki register pressure kamayishi mumkin.

Dependence cheklovi

Fission statementlar orasidagi dependence yo‘nalishini buzmasligi kerak. Birinchi guruhdagi statement ikkinchi guruhga shu iteratsiyada qiymat bersa, guruh tartibi saqlanadi. Ikkinchi statement kelajak iteratsiyadan oldingi guruh qiymatini talab qilsa, barcha birinchi siklni oldin bajarish semantikani o‘zgartirishi mumkin.

Qo‘shimcha xotira

Transformatsiya temporary scalar qiymatni iteratsiyalar oralig‘ida saqlashga majbur qilsa, scalar expansion orqali massiv yaratilishi mumkin; bu xotira xarajatini oshiradi. Side effectli chaqiriqlar yoki I/O statementlarining global tartibini o‘zgartirish odatda taqiqlanadi.

Graf asosidagi usul

Compiler strongly connected componentlarni dependence graphda guruhlaydi: cycle ichidagi statementlar ajratilmaydi. Keyin komponentlar topological tartibda sikllarga taqsimlanadi. Profitability modeli cache, vectorization, parallelism va qo‘shimcha loop overheadni hisobga oladi.

Tekshirish

Testlar loop-carried dependence, alias qiluvchi massiv, zero trip count va overflowli induction variable bilan bajariladi. Har yangi siklning boundlari original iteration domainni aynan qamrashi tekshiriladi. Memory traffic counter fission haqiqatan localityni yaxshilaganini yoki yomonlashtirganini ko‘rsatadi.

Loop Fission bo‘yicha tahlil natijasi faqat yakuniy xulosa bilan emas, uni hosil qilgan IR versiyasi, target xususiyatlari va qo‘llangan taxminlar bilan birga saqlanadi. Compiler passlari ketma-ket o‘zgarganda oldingi natija avtomatik ravishda haqiqiy deb olinmaydi: tegishli dependencylar invalidatsiya qilinib, zarur qism qayta hisoblanadi. Debug rejimida asosiy invariant buzilgan nuqta va undan oldingi transformatsiya qayd etiladi; release rejimida esa tekshiruvlarning arzon qismi qoldiriladi. Shu yondashuv nazariy jihatdan qonuniy qoida implementatsiya xatosi yoki noto‘g‘ri cost model sabab zararli qarorga aylangan holatni ajratishga yordam beradi.

Kengaytirilgan jihatlar

Fission ko‘pincha loop bodydagi shartli, vectorize bo‘lmaydigan yoki kam bajariladigan qismni issiq arifmetik qismdan ajratadi. Masalan, avval flaglar hisoblanib, keyin compacted indekslar ustida alohida loop ishlashi mumkin. Biroq ajratilgan looplar orasida katta temporary array materializatsiyasi memory bandwidthni oshiradi. Compiler distributiondan keyin dead array elimination yoki scalar replacement qilolsa foyda qaytadi. Parallel regionda har yangi loop orasiga barrier qo‘shish zarurati paydo bo‘lishi mumkin; barrier xarajati kichik body foydasidan katta bo‘lishi ehtimol. Profil va target thread modeli shu sabab muhim.

Fissiondan keyin har hosil bo‘lgan loop alohida vectorization va parallelization kandidati sifatida tahlil qilinadi. Pass manager dependence analysisni eski loop identity bilan cache’da qoldirmaydi. Debugger step tartibi source statementlarining original aralash ketma-ketligidan farq qilishi mumkin; optimized buildda bu kutiladigan holat, lekin observable side effectlar o‘zgarmaydi.

Distribution remark statement guruhlari va ularni ajratishga to‘sqinlik qilgan strongly connected componentni ko‘rsatadi. Bu source rewrite bilan imkoniyatni ochish mumkinligini tushuntiradi.

Bog‘liq tushunchalar

loop fusion, loop distribution, data dependence, vectorization, scalar expansion, cache locality