題目描述
生命遊戲中,對於任意細胞,規則如下:
每個細胞有兩種狀態-存活或死亡,每個細胞與以自身為中心的周圍八格細胞產生互動。
- 當前細胞為存活狀態時,當周圍低於 2 個 (不包含 2 個) 存活細胞時,該細胞變成死亡狀態。
- 當前細胞為存活狀態時,當周圍有 2 個或 3 個存活細胞時, 該細胞保持原樣。
- 當前細胞為存活狀態時,當周圍有 3 個以上的存活細胞時,該細胞變成死亡狀態。
- 當前細胞為死亡狀態時,當周圍有 3 個存活細胞時,該細胞變成存活狀態。
可以把最初的細胞結構定義為種子,當所有在種子中的細胞同時被以上規則處理後,可以得到第一代細胞圖。按規則繼續處理當前的細胞圖,可以得到下一代的細胞圖,周而復始。
輸入格式
輸入第一行有兩個整數 $N$, $M$,表示盤面大小為 $N \times N$,模擬週期次數 $M$。接下來會有 $N$ 行,每一行上會有 $N$ 個字符,以 0
表示 $(i, j)$ 格子上的細胞屬於死亡狀態,反之 1
為存活狀態。
- $1 \le N \le 2000$
- $0 \le M \le 1000$
輸出格式
對於每一組測資輸出 $N$ 行,每一行上有 $N$ 個字元表示模擬 $M$ 次的最終盤面結果。
範例輸入 1
|
|
範例輸出 1
|
|
範例輸入 2
|
|
範例輸出 2
|
|
Solution
在還沒有做任何平行前,生命遊戲的模擬非常簡單,只需要統計鄰近八格的狀態即可,然而由於是常數範圍,直接打八個加法比起迴圈去累計八格的結果快上非常多,別忽視 for loop 在做 branch 的 cycle 數量。
- 樸素平行 Accepted (378 ms, 24 MB)
- 循環展開 Accepted (289 ms, 39 MB)
平行採用 big chunk 的方式,考慮到 cache miss 的關係,最好是每一個處理器都把相鄰的列放置在各自的 L1-L2-L3 cache,防止使用時不在自己的 cache,而產生嚴重的 cache miss。
|
|
循環展開
|
|