Try   HackMD

2017q1 Homework1(raytracing)

contributed by<yanang>

tags: yanang

進度落後請加緊腳步!
課程助教

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
  • $ 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 。
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

  • 參閱了 去年的共筆 當中 POSIX Thread 這段,將 raytracing() 做 thread 以達到將一張圖切分成數份去做繪製。
  • 稍微有點忘記 pthread 的用法,跟 data 的傳輸。
    參考 POSIX執行緒pthread_data
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
CC ?= gcc CFLAGS = \ -std=gnu99 -Wall -O0 -g LDFLAGS = \ -lm -lpthread
  • 一開始只使用一個 struct para *ptr 去處理所有資料,忘了 pointer 特性,所以畫出來的圖總是缺角,原先一直以為某一小段寫錯了,最後才想起。
para *ptr = malloc(sizeof(para)); ptr->pixels = pixels; ptr->rectangulars = rectangulars; ... pthread_create(&pid0, NULL, raytracing, (void *)ptr);

  • 後改用宣告為矩陣
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 ,未修改結果

  • 修改後測試 (回復正常的圖)

  • $ ./rayracing

# Rendering scene
Done!
Execution time of raytracing() : 0.963422 sec
  • 總比較圖:

-O0 -Ofast

  • 記得在 作業解說 裡有提到,若要得到最佳效能能使用 -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