Try   HackMD

2017q1 Homework5 (matrix)

contributed by < illusion030 >


開發環境

illusion030@illusion030-X550LD:~/Desktop/2017sysprog/matrix_oo$ lscpu
Architecture:          x86_64
CPU 作業模式:    32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                4
On-line CPU(s) list:   0-3
每核心執行緒數:2
每通訊端核心數:2
Socket(s):             1
NUMA 節點:         1
供應商識別號:  GenuineIntel
CPU 家族:          6
型號:              69
Model name:            Intel(R) Core(TM) i5-4200U CPU @ 1.60GHz
製程:              1
CPU MHz:             1691.168
CPU max MHz:           2600.0000
CPU min MHz:           800.0000
BogoMIPS:              4589.15
虛擬:              VT-x
L1d 快取:          32K
L1i 快取:          32K
L2 快取:           256K
L3 快取:           3072K
NUMA node0 CPU(s):     0-3

重現實驗

SSE

  • 先將 sse 版本整合過來,發現一個問題是 Matrix Multiplication using SIMD 是用 integer 的矩陣相乘,但是在 matrix_oo 的 naive 版本是用 float 型態的矩陣
  • 先用 integer 型態的矩陣相乘實作看看
  • 測試結果
Execute tests/test-matrix...
naive result equal!!
sse result equal!!
OK!

相乘結果是正確的

克服 Matrix 大小的限制

  • 嘗試克服 Matrix 大小只有 4x4 的限制

  • 改成傳入二維陣列

static void assign(Matrix *thiz, int row, int col, int **data)
  • 遇到問題,在PRIV()裡需要 malloc 空間給 values,不然會 Segmentation fault
    上網查了一下資料
if (!(thiz->priv = malloc(thiz->row * thiz->col * sizeof(int))))
    return;
if (!(PRIV(thiz)->values = (int **)malloc(row * sizeof(int *))))
    return;
for (i = 0; i < thiz->row; i++)
    if (!(PRIV(thiz)->values[i] = (int *)malloc(thiz->col * sizeof(int)))) 
        return;
  • 對 mul 的 dst 也做一樣的事
if (!(dst->priv = malloc(l->row * r->col * sizeof(int))))
    return false;
if (!(PRIV(dst)->values = (int **)malloc(l->row * sizeof(int *))))
    return false;
for (i = 0; i < l->row; i++)
    if(!(PRIV(dst)->values[i] = (int *)malloc(r->col * sizeof(int))))
        return false;
  • 發現原本的 code 沒有給 dst->row 跟 dst->col 值,把他加進去
dst->row = l->row;
dst->col = r->col;

解決 SSE 的 matrix size 限制

  • 在 Matrix 的 row 跟 col 不為 4 的倍數時將他 extend 成 4 的倍數,多出來的部份補 0,在最後把 row 跟 col 改成我們要的數字
/* extend while not the multiple of 4 */
thiz->row = (row % 4 == 0) ? row : row + (4 - row % 4); 
thiz->col = (col % 4 == 0) ? col : col + (4 - col % 4);
for (i = 0; i < thiz->row; i++) {
    for (j = 0; j < thiz->col; j++) {
        if (i >= row || j >= col)
            PRIV(thiz)->values[i][j] = 0;
thiz->row = row;
thiz->col = col;
  • 對 dst 做同樣的 extend
/* extend while not the multiple of 4 */
dst->row = (l->row % 4 == 0) ? l->row : l->row + (4 - l->row % 4);
dst->col = (r->col % 4 == 0) ? r->col : r->col + (4 - r->col % 4);
same_line = (l->col % 4 == 0) ? l->col : l->col + (4 - l->col % 4);
dst->row = l->row;
dst->col = r->col;