CSAPP实验四:性能优化实验(Perflab)
? ? ? ?本系列文章為中國科學(xué)技術(shù)大學(xué)計算機(jī)專業(yè)學(xué)科基礎(chǔ)課《計算機(jī)系統(tǒng)》布置的實(shí)驗,上課所用教材和內(nèi)容為黑書CSAPP,當(dāng)時花費(fèi)很大精力和彎路,現(xiàn)來總結(jié)下各個實(shí)驗,本文章為第四個實(shí)驗——性能優(yōu)化實(shí)驗(Perflab)。
一、實(shí)驗名稱:perflab
二、實(shí)驗學(xué)時: 3
三、實(shí)驗內(nèi)容和目的:
? ? ? ?此次實(shí)驗進(jìn)行圖像處理代碼的優(yōu)化。圖像處理提供了許多能夠通過優(yōu)化而得到改良的函數(shù)。在此次實(shí)驗中,我們將考慮兩種圖像處理操作:roate, 此函數(shù)用于將圖像逆時針旋轉(zhuǎn)90°;以及smooth,對圖像進(jìn)行“平滑”或者說“模糊”處理。
? ? ? ?對于此次實(shí)驗,我們將認(rèn)為圖像是以一個二維矩陣 M?來表示的,并以 Mi,j?來表記(i,j)位置的像素值。像素值是由紅,綠,藍(lán)(RGB)三個值構(gòu)成的三元組。我們僅考慮方形圖像。以 N?來表記圖像的行數(shù)(同時也是列數(shù))。行和列均以C風(fēng)格進(jìn)行編號——從0到 N - 1?。
? ? ? ?在這種表示方法之下,rotate?操作可以借由以下兩種矩陣操作的結(jié)合來簡單實(shí)現(xiàn):
- 轉(zhuǎn)置:對于每個(i,j),交換 Mi,j?與 Mj,i?。
- 行交換:交換第 i 行與第 N?- 1 - i 行。
? ? ? ?詳情見下圖:
? ? ? ? smooth?操作可以通過求每個像素與周圍像素(最多是以該像素為中心的3×3的九宮格)的均值。詳見圖2,像素 M2[1][1] 與 M2[N - 1][N - 1] 由下式給出:
?四、實(shí)驗步驟及結(jié)果:
? ? ? ? 首先將 perflab-handout.tar 拷貝至一個受保護(hù)的文件夾,用于完成此次實(shí)驗。
? ? ? ? 然后在命令行輸入命令:tar xvf perflab-handout.tar 這將使數(shù)個文件被解壓至當(dāng)前目錄。
? ? ? ? 你可以進(jìn)行修改并最終提交的唯一文件是 kernels.c 程序 driver.c 是一個驅(qū)動程序,你可以用它來評估你解決方案的性能。使用命令:make driver 來生成驅(qū)動代碼,并用命令 ./driver 來使其運(yùn)行。
? ? ? ? 查看文件 kernels.c,你會發(fā)現(xiàn)一個C 結(jié)構(gòu)體:team。你需要將你小組成員的信息填入其中。請馬上填寫,以防你忘記。
? ? ??1.naive_rotate
/**naive_rotate - The naive baseline version of rotate*/ char naive_rotate_descr[] ="naive_rotate: Naive baseline implementation"; void naive_rotate(int dim, pixel *src,pixel *dst) {int i, j;for (i = 0; i < dim; i++)for(j = 0; j < dim; j++)dst[RIDX(dim-1-j, i, dim)] = src[RIDX(i, j,dim)]; }?? ? ? ? 在頭文件defs.h中找到了宏定義:
#defineRIDX(i,j,n) ((i)*(n)+(j))? ? ? ? 那么這段代碼就很容易為一幅畫的旋轉(zhuǎn),它將將所有的像素進(jìn)行行列調(diào)位、導(dǎo)致整幅圖畫進(jìn)行了90度旋轉(zhuǎn)。
? ? ? ? 但是由于這串代碼的步長太長,導(dǎo)致cache的命中率非常低,所以總體運(yùn)算效率低。因此,我們考慮到cache的大小,應(yīng)在存儲的時候進(jìn)行32個像素依次存儲(列存儲)。(32個像素排列是為了充分利用一級緩存(32KB), 采用分塊策略, 每一個塊大小為32)
? ? ? ? 這樣可以做到cache友好、可以大幅度提高效率。
? ? ??2.perf_rotate
? ? ? ? 考慮矩形分塊32*1,32路循環(huán)展開,并使dest地址連續(xù),以減少存儲器寫次數(shù)
//宏定義一個復(fù)制函數(shù),方便程序編寫 #define COPY(d,s) *(d)=*(s) char rotate_descr[] = "rotate: Currentworking version";void rotate( int dim,pixel *src,pixel *dst) {int i,j;for(i=0;i<dim;i+=32)//32路循環(huán)展開,32個像素依次存儲for(j=dim-1;j>=0;j-=1) { pixel*dptr=dst+RIDX(dim-1-j,i,dim);pixel*sptr=src+RIDX(i,j,dim); //進(jìn)行復(fù)制操作COPY(dptr,sptr);sptr+=dim;COPY(dptr+1,sptr);sptr+=dim;COPY(dptr+2,sptr);sptr+=dim;COPY(dptr+3,sptr);sptr+=dim;COPY(dptr+4,sptr);sptr+=dim;COPY(dptr+5,sptr);sptr+=dim;COPY(dptr+6,sptr);sptr+=dim;COPY(dptr+7,sptr);sptr+=dim;COPY(dptr+8,sptr);sptr+=dim;COPY(dptr+9,sptr);sptr+=dim;COPY(dptr+10,sptr);sptr+=dim;COPY(dptr+11,sptr);sptr+=dim;COPY(dptr+12,sptr);sptr+=dim;COPY(dptr+13,sptr);sptr+=dim;COPY(dptr+14,sptr);sptr+=dim;COPY(dptr+15,sptr);sptr+=dim;COPY(dptr+16,sptr);sptr+=dim;COPY(dptr+17,sptr);sptr+=dim;COPY(dptr+18,sptr);sptr+=dim;COPY(dptr+19,sptr);sptr+=dim;COPY(dptr+20,sptr);sptr+=dim;COPY(dptr+21,sptr);sptr+=dim;COPY(dptr+22,sptr);sptr+=dim;COPY(dptr+23,sptr);sptr+=dim;COPY(dptr+24,sptr);sptr+=dim;COPY(dptr+25,sptr);sptr+=dim;COPY(dptr+26,sptr);sptr+=dim;COPY(dptr+27,sptr);sptr+=dim;COPY(dptr+28,sptr);sptr+=dim;COPY(dptr+29,sptr);sptr+=dim;COPY(dptr+30,sptr);sptr+=dim;COPY(dptr+31,sptr); } }? ? ? 3.smooth
char naive_smooth_descr[] ="naive_smooth: Naive baseline implementation"; void naive_smooth(int dim, pixel *src,pixel *dst) {int i, j;for (i = 0; i < dim; i++)for (j = 0; j < dim; j++)dst[RIDX(i, j, dim)] = avg(dim, i, j, src); }? ? ? ? 這段代碼頻繁地調(diào)用avg函數(shù),并且avg函數(shù)中也頻繁調(diào)用initialize_pixel_sum?、accumulate_sum、assign_sum_to_pixel這幾個函數(shù),且又含有2層for循環(huán),而我們應(yīng)該減少函數(shù)調(diào)用的時間開銷。所以,需要改寫代碼,不調(diào)用avg函數(shù)。?
? ? ? ? 特殊情況,特殊對待:
? ? ? ? Smooth函數(shù)處理分為4塊,一為主體內(nèi)部,由9點(diǎn)求平均值;二為4個頂點(diǎn),由4點(diǎn)求平均值;三為四條邊界,由6點(diǎn)求平均值。從圖片的頂部開始處理,再上邊界,順序處理下來,其中在處理左邊界時,for循環(huán)處理一行主體部分,于是就有以下優(yōu)化的代碼。
? ? ? 4.perf_smooth
charsmooth_descr[] = "smooth: Current working version"; void smooth(intdim, pixel* src, pixel* dst) {int i, j;int dim0 = dim;int dim1 = dim - 1;int dim2 = dim - 2;pixel* P1, * P2, * P3;pixel* dst1;P1 = src;P2 = P1 + dim0;//左上角像素處理 采用移位運(yùn)算代替avg的某些操作dst->red = (P1->red + (P1 + 1)->red + P2->red + (P2 + 1)->red) >> 2; dst->green = (P1->green + (P1 + 1)->green + P2->green + (P2 + 1)->green) >> 2; dst->blue = (P1->blue + (P1 + 1)->blue + P2->blue + (P2 + 1)->blue) >> 2;dst++;//上邊界處理 for (i = 1; i < dim1; i++) {dst->red = (P1->red + (P1 + 1)->red + (P1 + 2)->red + P2->red + (P2 + 1)->red + (P2 + 2)->red) / 6; dst->green = (P1->green + (P1 + 1)->green + (P1 + 2)->green + P2->green + (P2 + 1)->green + (P2 + 2)->green) / 6; dst->blue = (P1->blue + (P1 + 1)->blue + (P1 + 2)->blue + P2->blue + (P2 + 1)->blue + (P2 + 2)->blue) / 6;dst++;P1++;P2++;}//右上角像素處理 dst->red=(P1->red+(P1+1)->red+P2->red+(P2+1)->red)>>2; dst->green = (P1->green + (P1 + 1)->green + P2->green + (P2 + 1)->green) >> 2; dst->blue = (P1->blue + (P1 + 1)->blue + P2->blue + (P2 + 1)->blue) >> 2;dst++;P1 = src;P2 = P1 + dim0;P3 = P2 + dim0;//左邊界處理 for (i = 1; i < dim1; i++) {dst->red = (P1->red + (P1 + 1)->red + P2->red + (P2 + 1)->red + P3->red + (P3 + 1)->red) / 6; dst->green = (P1->green + (P1 + 1)->green + P2->green + (P2 + 1)->green + P3->green + (P3 + 1)->green) / 6; dst->blue = (P1->blue + (P1 + 1)->blue + P2->blue + (P2 + 1)->blue + P3->blue + (P3 + 1)->blue) / 6;dst++;dst1 = dst + 1;}//主體中間部分處理 for (j = 1; j < dim2; j += 2) {//同時處理2個像素 dst->red = (P1->red + (P1 + 1)->red + (P1 + 2)->red + P2->red + (P2 + 1)->red + (P2 + 2)->red + P3->red + (P3 + 1)->red + (P3 + 2)->red) / 9;dst->green = (P1->green + (P1 + 1)->green + (P1 + 2)->green + P2->green + (P2 + 1)->green + (P2 + 2)->green + P3->green + (P3 + 1)->green + (P3 + 2)->green) / 9;dst->blue = (P1->blue + (P1 + 1)->blue + (P1 + 2)->blue + P2->blue + (P2 + 1)->blue + (P2 + 2)->blue + P3->blue + (P3 + 1)->blue + (P3 + 2)->blue) / 9;dst1->red = ((P1 + 3)->red + (P1 + 1)->red + (P1 + 2)->red + (P2 + 3)->red + (P2 + 1)->red + (P2 + 2)->red + (P3 + 3)->red + (P3 + 1)->red + (P3 + 2)->red) / 9;dst1->green = ((P1 + 3)->green + (P1 + 1)->green + (P1 + 2)->green + (P2 + 3)->green + (P2 + 1)->green + (P2 + 2)->green + (P3 + 3)->green + (P3 + 1)->green + (P3 + 2)->green) / 9;dst1->blue = ((P1 + 3)->blue + (P1 + 1)->blue + (P1 + 2)->blue + (P2 + 3)->blue + (P2 + 1)->blue + (P2 + 2)->blue + (P3 + 3)->blue + (P3 + 1)->blue + (P3 + 2)->blue) / 9;dst += 2; dst1 += 2; P1 += 2; P2 += 2; P3 += 2;}for (; j < dim1; j++) {dst->red = (P1->red + (P1 + 1)->red + (P1 + 2)->red + P2->red + (P2 + 1)->red + (P2 + 2)->red + P3->red + (P3 + 1)->red + (P3 + 2)->red) / 9;dst->green = (P1->green + (P1 + 1)->green + (P1 + 2)->green + P2->green + (P2 + 1)->green + (P2 + 2)->green + P3->green + (P3 + 1)->green + (P3 + 2)->green) / 9;dst->blue = (P1->blue + (P1 + 1)->blue + (P1 + 2)->blue + P2->blue + (P2 + 1)->blue + (P2 + 2)->blue + P3->blue + (P3 + 1)->blue + (P3 + 2)->blue) / 9;dst++; P1++; P2++; P3++;}//右側(cè)邊界處理 dst->red=(P1->red+(P1+1)->red+P2->red+(P2+1)->red+P3->red+(P3+1)->red)/6; dst->green=(P1->green+(P1+1)->green+P2->green+(P2+1)->green+P3->green+(P3+1)->green)/6; dst->blue=(P1->blue+(P1+1)->blue+P2->blue+(P2+1)->blue+P3->blue+(P3+1)->blue)/6; dst++; P1 += 2; P2 += 2; P3 += 2; } //左下角處理 dst->red=(P1->red+(P1+1)->red+P2->red+(P2+1)->red)>>2; dst->green = (P1->green + (P1 + 1)->green + P2->green + (P2 + 1)->green) >> 2; dst->blue = (P1->blue + (P1 + 1)->blue + P2->blue + (P2 + 1)->blue) >> 2; dst++; //下邊界處理 for (i = 1; i < dim1; i++) {dst->red = (P1->red + (P1 + 1)->red + (P1 + 2)->red + P2->red + (P2 + 1)->red + (P2 + 2)->red) / 6; dst->green = (P1->green + (P1 + 1)->green + (P1 + 2)->green + P2->green + (P2 + 1)->green + (P2 + 2)->green) / 6; dst->blue = (P1->blue + (P1 + 1)->blue + (P1 + 2)->blue + P2->blue + (P2 + 1)->blue + (P2 + 2)->blue) / 6;dst++; P1++; P2++; } //右下角像素處理 dst->red=(P1->red+(P1+1)->red+P2->red+(P2+1)->red)>>2; dst->green=(P1->green+(P1+1)->green+P2->green+(P2+1)->green)>>2; dst->blue=(P1->blue+(P1+1)->blue+P2->blue+(P2+1)->blue)>>2; //全部處理完畢 }? ? ? 5. 實(shí)驗結(jié)果
?對于rotate操作平均加速了13.1倍
?對于smooth操作平均加速了48.4倍
總結(jié)
以上是生活随笔為你收集整理的CSAPP实验四:性能优化实验(Perflab)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 写给大忙人看的谷歌搜索技巧
- 下一篇: 第6章 查询处理和查询优化