0

我需要一些关于并行工作负载分布的建议,基于热量分布问题,使用 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;
                    }
                }
            }
        }
    }
}
4

0 回答 0