【问题标题】:C# multithreading doesn't use enough cpuC# 多线程没有使用足够的 cpu
【发布时间】:2017-06-16 05:31:26
【问题描述】:

我正在尝试加快我用 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 task 更改为 4、6 和 8。没有大的变化。

我正在考虑 GC,但我无法阻止它运行。

编辑: 通过减少一些类的内存使用,我设法稍微提高了 CPU 使用率,现在它运行在 70% 左右。

另一方面,通过提高四叉树的水平阈值,我获得了实质性的性能提升。

【问题讨论】:

  • 每个单线程只能使用一个物理核心。也许这就是你所面临的。此外Task.WaitAll(tasks); 只会在所有任务完成后继续,因此其中一些可能在所有任务完成之前已经完成。
  • 您需要提供minimal reproducible example。我们真的应该有可以复制粘贴并运行以查看问题的代码。理想情况下,我们也应该有此代码的非并行版本,以便我们可以看到基本计算是什么。
  • 不确定你的意图是什么,但你可以让它平行并检查。简单的方法是使用 Parallel for 循环。您还可以设置再次依赖于处理器内核的处理器亲和性。
  • Enigmativity 不幸的是,我无法为您提供一个最小的示例,因为代码在框架中运行并且要使其正常工作,我必须在此处粘贴一半的应用程序。另外我正在为一家公司开发这个应用程序,我不能分享太多的算法。 @Souvik 必须对 otput 进行排序,因此使用 Parallel.For 会使事情变得更加复杂,而且还会产生创建一百万个委托的开销。
  • 那么我建议你创建异步函数任务并在for循环中调用它们。由于您需要一个有序的 for 循环,我认为最好减少循环的每次迭代中的执行时间。

标签: c# multithreading optimization


【解决方案1】:

因为您的段之间没有需要额外同步的依赖关系,所以我建议查看任务并行库 (TPL)。 Parallel.ForParallel.ForEach 可能对您来说很有趣。

要优化现有代码,有多种选择:

  • 删除TaskCreationOptions.LongRunning。它可能会产生新线程,这很耗时。
  • 创建您自己的任务调度程序并赋予底层线程更高的优先级。在试验 TPL 并行循环时也可以使用它。目前,您使用的是默认线程池,可能会被其他组件使用/阻塞。

更新: 另请参阅lowering priority of Task.Factory.StartNew thread,了解如何创建具有不同优先级的自定义任务调度程序。它工作得很好,我在几个项目中都使用了它。另请参阅 Stephen Toub 的博客。

【讨论】:

    猜你喜欢
    • 2012-03-02
    • 1970-01-01
    • 2012-04-09
    • 1970-01-01
    • 1970-01-01
    • 2011-08-03
    • 2011-02-09
    • 2019-11-07
    • 2012-09-17
    相关资源
    最近更新 更多