0

Jocobi メソッドを使用した、熱分布の問題に基づいた、並列作業負荷の分散に関するアドバイスが必要です。プログラムは、2D 配列を並列 for を介して 4 つの同じサイズのグリッドに分割することによって機能します。次に、小さなグリッドのそれぞれを、新しいタスクで処理される、たとえば 10 行の行クラスターにさらに分割します。初期のグリッド サイズは 10000x10000 です。

プログラムは動作しますが、2D 配列を分割せずに行をクラスタリングするなど、他の並列実装よりも大幅に遅くなります。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