# 2017q1 Homework1(raytracing) contributed by<`yanang`> ###### tags: `yanang` >進度落後請加緊腳步! >[name=課程助教][color=red] ### Reviewed by stanleytazi + 可以 Loop unrolling 記得還有其他的 math toolkit,可以對那些做更改再做比較 + 這邊捨去 double dp 的目的是什麼呢? 不捨去的效能會比較差嗎? + 看不太懂 Pthread 那邊由 malloc 改成 array 宣告的差別 + git commit 可以再多加一些描述來符合 "**Use the body to explain what and why vs. how**" ## 初步測試 * $ ./raytracing ``` # Rendering scene Done! Execution time of raytracing() : 2.817711 sec ``` * $ convert out.ppm out.png ![](https://i.imgur.com/9u2LxDQ.png) * $ make clean 後重新 $ make PROFILE=1 ``` # Rendering scene Done! Execution time of raytracing() : 5.906013 sec ``` * $ grof ./raytracing | less ``` Each sample counts as 0.01 seconds. % cumulative self self total time seconds seconds calls s/call s/call name 24.71 0.60 0.60 56956357 0.00 0.00 subtract_vector 21.00 1.11 0.51 69646433 0.00 0.00 dot_product 9.47 1.34 0.23 31410180 0.00 0.00 multiply_vector 8.24 1.54 0.20 17836094 0.00 0.00 add_vector 7.41 1.72 0.18 13861875 0.00 0.00 rayRectangularIntersection 5.76 1.86 0.14 13861875 0.00 0.00 raySphereIntersection 4.94 1.98 0.12 10598450 0.00 0.00 normalize ``` ## loop unrolling * 針對 dot_product() 將 loop 展開,同時捨去 double dp 。 ```c= double dot_product(const double *v1, const double *v2) { return (v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]); } ``` * $ ./rayracing ``` # Rendering scene Done! Execution time of raytracing() : 2.384672 sec sec ``` ## POSIX Thread * 參閱了 [去年的共筆](https://embedded2016.hackpad.com/ep/pad/static/f5CCUGMQ4Kp) 當中 POSIX Thread 這段,將 raytracing() 做 thread 以達到將一張圖切分成數份去做繪製。 * 稍微有點忘記 pthread 的用法,跟 data 的傳輸。 參考 [POSIX執行緒](https://zh.wikipedia.org/wiki/POSIX%E7%BA%BF%E7%A8%8B) 和 [pthread_data](http://stackoverflow.com/questions/1352749/multiple-arguments-to-function-called-by-pthread-create) ```c= typedef struct __PARAMETER{ uint8_t *pixels; rectangular_node rectangulars; sphere_node spheres; light_node lights; const viewpoint *view; int width_start; int width; int height_start; int height; } para; ``` * 因為 pthread 資料庫不是 Linux 系統默認的資料庫,連接時需要使用靜態庫 libpthread.a ```c= CC ?= gcc CFLAGS = \ -std=gnu99 -Wall -O0 -g LDFLAGS = \ -lm -lpthread ``` * 一開始只使用一個 struct para *ptr 去處理所有資料,忘了 pointer 特性,所以畫出來的圖總是缺角,原先一直以為某一小段寫錯了,最後才想起。 ```c= para *ptr = malloc(sizeof(para)); ptr->pixels = pixels; ptr->rectangulars = rectangulars; ... pthread_create(&pid0, NULL, raytracing, (void *)ptr); ``` ![](https://i.imgur.com/yfcSBmP.png) * 後改用宣告為矩陣 ```c= para ptr[4]; ptr[0].pixels = pixels; ptr[0].rectangulars = rectangulars; ... pthread_create(&pid0, NULL, raytracing, (void *)&ptr[0]); ``` * raytracing() 運算當中的 width 和 height 指的是邊界(512),而非輸入的最大 width 和 height ,未修改結果 ![](https://i.imgur.com/OPZusDO.png) * 修改後測試 (回復正常的圖) ![](https://i.imgur.com/FqLNQRa.png) * $ ./rayracing ``` # Rendering scene Done! Execution time of raytracing() : 0.963422 sec ``` * 總比較圖: ![](https://i.imgur.com/l1Hdw1u.png) ## -O0 -Ofast * 記得在 [作業解說](https://www.youtube.com/watch?v=m1RmfOfSwno) 裡有提到,若要得到最佳效能能使用 -Ofast ,所以想說再新增 thread 後再使用一次。 * 完全未修改的程式碼使用 -Ofast ``` # Rendering scene Done! Execution time of raytracing() : 0.806448 sec ``` * 增加 loop unrolling 後使用 -Ofast ``` # Rendering scene Done! Execution time of raytracing() : 0.654491 sec ``` * 增加 thread 後使用 -Ofast ``` # Rendering scene Done! Execution time of raytracing() : 0.272825 sec ```