C# 二维阵列的并行分布
我需要一些关于并行工作负载分配的建议,基于热分布问题,使用Jocobi方法。该程序通过并行for-then将2D阵列拆分为4个大小相等的网格,然后将每个较小的网格进一步分解为行簇,例如10行,这些行将在新任务中处理。初始网格大小为10000x1000 该程序可以工作,但它比我的其他并行实现(例如,在不拆分2D数组的情况下对行进行集群)要慢得多。即使使用for循环,也会有很多延迟。我不明白为什么,因为阵列的访问时间。例如,计算:x[50009999]y[50009999](右下角) 有人能解释这次抢劫的原因吗C# 二维阵列的并行分布,c#,parallel-processing,task-parallel-library,multidimensional-array,C#,Parallel Processing,Task Parallel Library,Multidimensional Array,我需要一些关于并行工作负载分配的建议,基于热分布问题,使用Jocobi方法。该程序通过并行for-then将2D阵列拆分为4个大小相等的网格,然后将每个较小的网格进一步分解为行簇,例如10行,这些行将在新任务中处理。初始网格大小为10000x1000 该程序可以工作,但它比我的其他并行实现(例如,在不拆分2D数组的情况下对行进行集群)要慢得多。即使使用for循环,也会有很多延迟。我不明白为什么,因为阵列的访问时间。例如,计算:x[50009999]y[50009999](右下角) 有人能解释这次
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;
}
}
}
}
}
}
类并行热分布
{
私人双[,]热网;
私有整数维;
专用int x1、x2、x3;
私人int y1、y2、y3;
私有整数[,]四维;
公共并行热分布(双[,]热网格,整数网格维度)
{
this.heatGrid=heatGrid;
this.gridDimensions=gridDimensions;
这是1.x1=1;
this.x2=this.gridDimensions/2;
这是1.y1=1;
this.y2=this.gridDimensions/2;
this.x3=this.gridDimensions-1;
this.y3=this.gridDimensions-1;
this.quadDimensions=新的int[4,4]{x1,x2,y1,y2},{x1,x2,y2,y3},{x2,x3,y1,y2},{x2,x3,y2,y3};
}
///
///启动并行分发
///
公共分布(int clusterRowCount)
{
对于(int i=0;i<1;i++)
{
分布式工作负载(clusterRowCount,quadDimensions[3,0],quadDimensions[3,1],quadDimensions[3,2],quadDimensions[3,3]);
}
对于(0,3,i=>
{
//分布式工作负载(clusterRowCount,quadDimensions[i,0],quadDimensions[i,1],quadDimensions[i,2],quadDimensions[i,3]);
});
}
///
///通过根据循环迭代的x数量将功分配给任务,并行计算热量分布。每个迭代代表一个数组行分区
///
私有void DistributeWorkload(int-clusterRowCount、int-xStartPoint、int-xEndpoint、int-yStartPoint、int-yEndpoint)
{
/*计算并行分发的数据分区群集*/
int clusterCount=(gridDimensions)/clusterRowCount;
/*黑白元素的并行任务阵列*/
Task[]taskArray1=新任务[clusterCount];
Task[]taskArray2=新任务[clusterCount];
尝试
{
/*为计算“黑色方块”的任务集分配工作*/
int c=0;
对于(int-x1=0;x1setTask(clusterRowCount、clusterSize、true、xStartPoint、xEndpoint、yStartPoint、yEndpoint));
c=c+集群行数;
}
/*将工作分配给第二组任务,计算“白色方块”*/
c=0;
对于(int x2=0;x2setTask(clusterRowCount、clusterSize、false、xStartPoint、xEndpoint、yStartPoint、yEndpoint));
c=c+集群行数;
}
/*启动所有任务*/
foreach(taskArray1中的任务t)t.Start();
Task.WaitAll(taskArray1);
foreach(taskArray2中的任务t)t.Start();
/*等等*/
Task.WaitAll(taskArray2);
}
捕获(聚合异常e)
{
控制台。写入(e);
}
}
///
///任务:计算一组行
///
///y轴位置
///确定网格元素集
公共void setTask(int-clusterRowCount、int-currentClusterCount、bool-isFirst、int-xStartPoint、int-xEndpoint、int-yStartPoint、int-yEndpoint)
{
int yPos=yStartPoint+currentClusterCount;
双温;
对于(int y=yPos;y
您的计算机有多少个CPU核心?如果是4(或更少),那么就没有理由在Parallel.for()中使用任务s。。。我在mo使用i3,但最终将在8核机器上运行。