我试图加快我用C#编写的算法。我想到的第一件事就是让它平行。
算法必须运行很多(〜数百万)个2D段,每个段独立于其他段。
这是代码:`
private void DoMapping(Segment[] image, CancellationToken ct, int numTasks = 3)
{
long time = Environment.TickCount;
LaserOutput = new List<Vector3[]>();
NormalsOutput = new List<Vector3>();
Task< Tuple < List<Vector3[]>, List < Vector3 >>>[] tasks = new Task<Tuple<List<Vector3[]>, List<Vector3>>>[numTasks];
int perTaskSegments = image.Length / numTasks;
for (int taskIndex = 0; taskIndex < tasks.Length; taskIndex++)
{
int nseg = perTaskSegments * (taskIndex + 1) + (taskIndex == tasks.Length - 1 ? image.Length % tasks.Length : 0);
int from = perTaskSegments * taskIndex;
Tuple<int, int, Segment[], CancellationToken> obj = new Tuple<int, int, Segment[], CancellationToken>(from, nseg, image, ct);
tasks[taskIndex] = Task.Factory.StartNew(DoComputationsAction, obj, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
Task.WaitAll(tasks);
for (int taskIndex = 0; taskIndex < tasks.Length; taskIndex++)
{
LaserOutput.AddRange(tasks[taskIndex].Result.Item1);
NormalsOutput.AddRange(tasks[taskIndex].Result.Item2);
}
}
private Tuple<List<Vector3[]>, List<Vector3>> DoComputationsAction(object obj)
{
Tuple<int, int, Segment[], CancellationToken> parm = obj as Tuple<int, int, Segment[], CancellationToken>;
List<Vector3[]> tmpLaser = new List<Vector3[]>();
List<Vector3> tmpNormals = new List<Vector3>();
bool errorOccured = false;
for (int segCounter = parm.Item1; segCounter < parm.Item2 && !errorOccured; segCounter++)
{
if (parm.Item4.IsCancellationRequested)
break;
try
{
var res = SplitOverMap(parm.Item3[segCounter], (string error) => {
errorOccured = true;
MessageBox.Show(error, "An error occured", MessageBoxButtons.OK, MessageBoxIcon.Error);
Logger.Log("An error occured while mapping data to 3d.");
});
if (res != null)
{
tmpLaser.AddRange(res.Item1);
tmpNormals.AddRange(res.Item2);
}
}
catch (Exception e)
{
Logger.Log("An error occured while calculating 3d map. Skipping polyline." + e.Message);
}
}
return new Tuple<List<Vector3[]>, List<Vector3>>(tmpLaser, tmpNormals);
}`
在SplitOverMap内部执行查询空间数据结构(QTree),然后进行一些计算。
在整个过程中,没有锁。 无磁盘。
您对可能导致cpu仅使用40-60的内容有什么建议吗?
我也尝试将num任务更改为4,6和8 。没有重大变化。
我正在考虑使用GC,但我无法做很多事情来防止它运行。
修改 通过减少某些类的内存使用量,我已经设法提高了一点cpu的使用率,现在它运行了大约70%。
另一方面,通过提高QuadTree的级别阈值,我获得了显着的性能提升。
答案 0 :(得分:4)
因为您的段之间没有需要额外同步的依赖关系,所以我建议您查看任务并行库(TPL)。 Parallel.For
或Parallel.ForEach
对您来说可能很有趣。
要优化现有代码,有以下几种选择:
TaskCreationOptions.LongRunning
。它可能会产生新的线程,这很费时间。<强>更新强> 另请参阅lowering priority of Task.Factory.StartNew thread,了解如何使用不同的优先级创建自定义任务计划程序。它工作得很好,我用它来做几个项目。另见Stephen Toub的博客。