我需要一些关于并行工作负载分布的建议,基于热量分布问题,使用 Jocobi 方法。该程序的工作原理是通过并行将 2D 数组拆分为 4 个大小相等的网格,然后将每个较小的网格进一步分解为例如 10 行的行簇,这些行簇将在新任务中进行处理。初始网格大小为 10000x10000。
该程序可以工作,但它比我的其他并行实现慢得多,例如集群行,而不拆分二维数组。即使使用 for 循环,也有很多滞后。由于数组的访问时间,我不明白为什么。例如,计算:x[5000, 9999] y[5000, 9999](右下角)
任何人都可以为劫持提供解释吗?
class ParallelHeatDistribution_QuadCluster
{
private double[,] heatGrid;
private int gridDimensions;
private int x1, x2, x3;
private int y1, y2, y3;
private int[,] quadDimensions;
public ParallelHeatDistribution_QuadCluster(double[,] heatGrid, int gridDimensions)
{
this.heatGrid = heatGrid;
this.gridDimensions = gridDimensions;
this.x1 = 1;
this.x2 = this.gridDimensions / 2;
this.y1 = 1;
this.y2 = this.gridDimensions / 2;
this.x3 = this.gridDimensions - 1;
this.y3 = this.gridDimensions - 1;
this.quadDimensions = new int[4, 4] {{x1, x2, y1, y2}, {x1, x2, y2, y3}, {x2, x3, y1, y2}, {x2, x3, y2, y3}};
}
/// <summary>
/// Start parallel distribution
/// </summary>
public void parallelDistribution(int clusterRowCount)
{
for (int i = 0; i < 1; i++)
{
DistributeWorkload(clusterRowCount, quadDimensions[3, 0], quadDimensions[3, 1], quadDimensions[3, 2], quadDimensions[3, 3]);
}
Parallel.For(0, 3, i =>
{
//DistributeWorkload(clusterRowCount, quadDimensions[i, 0], quadDimensions[i, 1], quadDimensions[i, 2], quadDimensions[i, 3]);
});
}
/// <summary>
/// Calculate heat distribution in parallel by assigning work to tasks based on x-amount of loop iterations. Each iteration represents an array row partition
/// </summary>
private void DistributeWorkload(int clusterRowCount, int xStartPoint, int xEndpoint, int yStartPoint, int yEndpoint)
{
/* calculate data partition cluster for parallel distribution. */
int clusterCount = (gridDimensions) / clusterRowCount;
/* Parallel task arrays for black and white elements */
Task[] taskArray1 = new Task[clusterCount];
Task[] taskArray2 = new Task[clusterCount];
try
{
/* assign work to for set of tasks calculating the "black squares" */
int c = 0;
for (int x1 = 0; x1 < clusterCount; x1++)
{
int clusterSize = c;
taskArray1[x1] = new Task(() => setTask(clusterRowCount, clusterSize, true, xStartPoint, xEndpoint, yStartPoint, yEndpoint));
c = c + clusterRowCount;
}
/* assign work to second set of tasks calculating the "white squares" */
c = 0;
for (int x2 = 0; x2 < clusterCount; x2++)
{
int clusterSize = c;
taskArray2[x2] = new Task(() => setTask(clusterRowCount, clusterSize, false, xStartPoint, xEndpoint, yStartPoint, yEndpoint));
c = c + clusterRowCount;
}
/* start all tasks */
foreach (Task t in taskArray1) t.Start();
Task.WaitAll(taskArray1);
foreach (Task t in taskArray2) t.Start();
/* and wait... */
Task.WaitAll(taskArray2);
}
catch (AggregateException e)
{
Console.Write(e);
}
}
/// <summary>
/// Task: calculate a cluster of rows
/// </summary>
/// <param name="y"> y-axis position </param>
/// <param name="isFirst"> determine grid element set </param>
public void setTask(int clusterRowCount, int currentClusterCount, bool isFirst, int xStartPoint, int xEndpoint, int yStartPoint, int yEndpoint)
{
int yPos = yStartPoint + currentClusterCount;
double temperature;
for (int y = yPos; y < yEndpoint; y++)
{
for (int x = xStartPoint; x < xEndpoint; x++)
{
if (isFirst && y % 2 == 0 || !isFirst && y % 2 != 0)
{
if (x % 2 == 0)
{
temperature = (heatGrid[y - 1, x] + heatGrid[y + 1, x] + heatGrid[y, x - 1] + heatGrid[y, x + 1]) / 4;
heatGrid[x, y] = temperature;
}
}
else
{
if (x % 2 != 0)
{
temperature = (heatGrid[y - 1, x] + heatGrid[y + 1, x] + heatGrid[y, x - 1] + heatGrid[y, x + 1]) / 4;
heatGrid[x, y] = temperature;
}
}
}
}
}
}