分享程式代碼相關筆記
目前文章總數:182 篇
最後更新:2025年 05月 31日
細胞由小而大,當細胞量大時運行處理效率提升比較,並且以 600 世代,CPU 與 GPU 的耗費時間多久才能完成
※每秒最快執行 10 次 0.1 秒觸發一次世代更新
像素 | 細胞數量 | 計算時間 |
512 * 512 | 262,144 | 600 次 |
1024 * 1024 | 1,048,576 | 600 次 |
2048 * 2048 | 4,194,304 | 600 次 |
4096 * 4096 | 16,777,216 | 600 次 |
以下是測試電腦的配置,規格在中階範圍:
1. CPU 與核心數 | : | Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz (12 CPUs), ~3.2GHz |
2. GPU 與顯示卡 | : | Nvdia GeForce RTX 2060 12G |
3. DirectX 版本 | : | DirectX 12 |
4. 記憶體 | : | 48 GB |
5. 作業系統版本 | : | Windows 10 專業版 64 位元 |
6. 運算時間 | : | 每 100 Tric 觸發一次 (每秒10次),並且觸發 600 次就停止 |
7. ILGPU 版本 | : | 1.5.2 |
8. C# 版本 | : | 8.0 |
補充此規格的研究特點:
硬體 | 補充描述 | 評價 |
---|---|---|
CPU: i7-8700 (6C/12T) | 第 8 代 Intel CPU 仍為中接 | 中階效能代表,多數開發者機器仍使用同等級 |
GPU: RTX 2060 (12GB VRAM) | 支援 CUDA Cores 約 2176,對 ILGPU 非常友好 | 中階 GPU,但適合大量平行處理場景 |
記憶體: 48GB RAM | 可測試大型 2D 網格(4096 * 4096 綽綽有餘) | 在此次比較效能的過程中,可排除記憶體瓶頸 |
ILGPU 1.5.2 + DirectX 12 | LGPU 最新穩定版,支援 CUDA / OpenCL | 完整支援 GPU 平行化 |
系統資訊圖:
CPU天梯排名中 I7-8700 屬於中階 CPU(放在2025)
GPU 顯卡天梯排名RTX 2060 12G 版本亦屬於中階顯卡(放在2025)
基本測試方針:
1. 多次測試 | : | 對每種方法執行至少 5 次測試,取平均值以減少偶然誤差。 |
2. 記錄時間 | : | 除了總耗費時間外,還可以記錄每個操作的平均耗時和最大耗時,並且各執行 5 次 |
3. 硬體設備 | : | 所有測試都使用相同配備。 |
4. 相同次數 | : | 600 次生命週期,每秒最多觸發 10 次 |
CPU 的代碼,可參考0008. 康威生命遊戲(Game Of Life) - 細胞自動機模擬與程序化生成
調整後的代碼在啟動時會有選項
GPU 的代碼也調整於此範例代碼中
在 Nuget 中引用 ILGPU
專案中的 3-4. 啟動代碼時,會先判斷有無顯卡,若有才允許使用平行運算
並且在 3-5. 步驟時會設定使用 GpuKernel 方法
// 3-4. 初始化 ILGPU
context = Context.CreateDefault();
try
{
// GPU
accelerator = context.CreateCudaAccelerator(0);//電腦沒有顯示卡,此行會報錯
}
catch
{
// CPU
accelerator = context.CreateCPUAccelerator(0);
}
// 3-5. 設定 kernel 方法
kernel = accelerator.LoadAutoGroupedStreamKernel<Index2D, ArrayView2D<byte, Stride2D.DenseX>, ArrayView2D<byte, Stride2D.DenseX>>(GpuKernel);
實際上的 GpuKernel 就是康威生命遊戲的規則
/// <summary>
/// 5. GPU 核心程式 - 康威生命遊戲的規則 與 3-5 , 4-2 相互關聯
/// </summary>
static void GpuKernel(Index2D index, ArrayView2D<byte, Stride2D.DenseX> current, ArrayView2D<byte, Stride2D.DenseX> next)
{
// 5-1. Game of Life 計算
// 備註: xAxis, yAxis 代表細胞座標
// 備註: gridX, gridY 代表鄰居偏移量
int x = index.X;
int y = index.Y;
int width = current.IntExtent.X;
int height = current.IntExtent.Y;
// 5-2. 計算鄰居數量
int count = 0;
for (int yAxis = -1; yAxis <= 1; yAxis++)
{
for (int xAxis = -1; xAxis <= 1; xAxis++)
{
if (xAxis == 0 && yAxis == 0) continue;
// 處理邊界(環繞)
int nx = (x + xAxis + width) % width;
int ny = (y + yAxis + height) % height;
count += current[new Index2D(nx, ny)];
}
}
byte alive = current[index];
// 5-3. Game of Life 規則
if (alive == 1 && (count < 2 || count > 3))
next[index] = 0; // 死亡
else if (alive == 0 && count == 3)
next[index] = 1; // 誕生
else
next[index] = alive; // 保持原狀
}
在 4-2. 時( Timer 中) 才會真正執行 GPU 的平行運算處理
// 4-2. 執行 kernel - 傳遞 View 給 kernel (在步驟 3-5. 宣告方法)
kernel(new Index2D(WidthCells, HeightCells), bufferCurrent.View, bufferNext.View);
Cpu 與 GPU 5 次執行結果如下
次數 | CPU 測試 | GPU 測試 |
---|---|---|
1. | 耗費:65.69 秒 | 耗費:65.68 秒 |
2. | 耗費:65.71 秒 | 耗費:65.72 秒 |
3. | 耗費:65.72 秒 | 耗費:65.71 秒 |
4. | 耗費:65.73 秒 | 耗費:65.69 秒 |
5. | 耗費:65.77 秒 | 耗費:65.68 秒 |
整理最大值、最小值、平均數
項目 | CPU 測試 | GPU 測試 |
---|---|---|
最大值 | 65.77 秒 | 65.72 秒 |
最小值 | 65.69 秒 | 65.68 秒 |
5次平均值 | 65.72 秒 | 65.70 秒 |
擷取自一張 CPU 執行結果圖 512 * 512,其餘略
Cpu 與 GPU 5 次執行結果如下
次數 | CPU 測試 | GPU 測試 |
---|---|---|
1. | 耗費:65.96 秒 | 耗費:65.68 秒 |
2. | 耗費:65.97 秒 | 耗費:65.67 秒 |
3. | 耗費:65.80 秒 | 耗費:65.70 秒 |
4. | 耗費:66.05 秒 | 耗費:65.72 秒 |
5. | 耗費:65.16 秒 | 耗費:65.69 秒 |
整理最大值、最小值、平均數
項目 | CPU 測試 | GPU 測試 |
---|---|---|
最大值 | 66.05 秒 | 65.72 秒 |
最小值 | 65.16 秒 | 65.67 秒 |
5次平均值 | 65.79 秒 | 65.69 秒 |
擷取自一張 CPU 執行結果圖 1024 * 1024,其餘略
Cpu 與 GPU 5 次執行結果如下
次數 | CPU 測試 | GPU 測試 |
---|---|---|
1. | 耗費:226.63 秒 | 耗費:74.96 秒 |
2. | 耗費:228.07 秒 | 耗費:76.22 秒 |
3. | 耗費:232.45 秒 | 耗費:77.91 秒 |
4. | 耗費:226.77 秒 | 耗費:73.29 秒 |
5. | 耗費:235.81 秒 | 耗費:75.66 秒 |
整理最大值、最小值、平均數
項目 | CPU 測試 | GPU 測試 |
---|---|---|
最大值 | 235.81 秒 | 77.91 秒 |
最小值 | 226.77 秒 | 73.29 秒 |
5次平均值 | 229.95 秒 | 75.61 秒 |
擷取自一張 CPU 執行結果圖 2048 * 2048,其餘略
Cpu 與 GPU 5 次執行結果如下
次數 | CPU 測試 | GPU 測試 |
---|---|---|
1. | 耗費:1,589.92 秒 | 耗費:498.77 秒 |
2. | 耗費:1,584.38 秒 | 耗費:502.84 秒 |
3. | 耗費:1,572.89 秒 | 耗費:493.25 秒 |
4. | 耗費:1,601.44 秒 | 耗費:506.59 秒 |
5. | 耗費:1,596.71 秒 | 耗費:495.63 秒 |
整理最大值、最小值、平均數
項目 | CPU 測試 | GPU 測試 |
---|---|---|
最大值 | 1,601.44 秒 | 502.84 秒 |
最小值 | 1,572.89 秒 | 493.25 秒 |
5次平均值 | 1,589.07 秒 | 499.42 秒 |
擷取自一張 CPU 執行結果圖 4096 * 4096,其餘略
擷取自一張 GPU 執行結果圖 4096 * 4096,其餘略
平均時間與補充備註:
執行細胞數量 | CPU 5次平均總耗時(秒) | GPU 5次平均總耗時 |
---|---|---|
512 * 512 | 65.72 秒 | 65.70 秒 |
1024 * 1024 | 65.79 秒 | 65.69 秒 |
2048 * 2048 | 229.95 秒 | 75.61 秒 |
4096 * 4096 | 1,589.07 秒 | 499.42 秒 |
GPU 相對於 CPU 的效能比較 |
GPU 相對於 CPU 的效能提升倍數 |
分析與結論:
尺寸 | 結論 |
---|---|
小尺寸 512 * 512 與 1024 * 1024 | GPU 優勢不明顯,原因可能是 GPU 啟動與資料傳輸成本抵銷了平行處理帶來的效益。 |
中尺寸 2048 * 2048 | GPU 開始展現優勢,速度為 CPU 的約 3 倍以上。 |
大尺寸 4096 * 4096 | GPU 表現壓倒性勝出,CPU 花費超過 GPU 三倍以上時間,明顯不適合處理超大型網格。 |