前言
運行平行程式之前,要將資料切成很多塊,每一塊之間獨立。從邏輯上看來有 row-based, column-based, matrix-based, tree-based 等平行方法。在許多方法中,最容易入手的就是 row-based。
假設有 $n$ 個元素,編號介於 $[0, n-1]$ 之間,要分成 $m$ 組。每一組得編號都要連續,以增加資料局部性 (data locality) 並且每一塊大小盡可能一樣,請問要怎麼分割才好?這樣的數學問題要做出來並不是件難事,但強迫症的人來說,在程式中零碎的判斷相當折騰。
數學分析
直觀
若有 $n$ 個元素分成 $m$ 組,每一個組至少有 $\lfloor n / m \rfloor$ 個元素,其中 $n \mod m$ 組會額外多一個元素。因此,對於第 $i$ 組滿足 $i < n \mod m$ 都會多一個元素。
|
|
程序流
這方式屬於懶惰程序員,根據整數的性質會得到刻度,在計算第 $i$ 個刻度採用 $\lfloor \frac{in}{m} \rfloor$,自然而然地可以與下一個刻度形成一個區間。不幸地,若 $m > n$ 時,有些刻度會重疊,導致重複計算的情況發生。
|
|
ceil
從《具體數學》第三章節的介紹,得到幾個簡單的數學公式
$$\begin{align} n = \left \lceil \frac{n}{m} \right \rceil + \left \lceil \frac{n-1}{m} \right \rceil + \cdots + \left \lceil \frac{n-m-1}{m} \right \rceil \end{align}$$第 $i$ 團 ($0 \le i < m$),要處理 $\left \lceil \frac{n-i}{m} \right \rceil$ 個元素。
|
|
floor
又或者使用 floor 表示法
$$\begin{align} n = \left \lfloor \frac{n}{m} \right \rfloor + \left \lfloor \frac{n+1}{m} \right \rfloor + \cdots + \left \lfloor \frac{n+m-1}{m} \right \rfloor \end{align}$$第 $i$ 團 ($0 \le i < m$),要處理 $\left \lceil \frac{n+i}{m} \right \rceil$ 個元素。
|
|
補充流
不管怎樣,前 $i$ 就拿取 $\lceil \frac{n}{m} \rceil$,最後一組拿少一點。
|
|
測試
|
|