Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C多线程没有使用足够的cpu_C#_Multithreading_Optimization - Fatal编程技术网

C# C多线程没有使用足够的cpu

C# C多线程没有使用足够的cpu,c#,multithreading,optimization,C#,Multithreading,Optimization,我正在尝试加速我用C写的一个算法。我想到的第一件事是使它并行 该算法必须在数百万个2D段上运行,每个段相互独立 下面是代码:` private void DoMapping(Segment[] image, CancellationToken ct, int numTasks = 3) { long time = Environment.TickCount; LaserOutput = new List<Vector3[]>();

我正在尝试加速我用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的原因有任何建议

我还尝试将numtask更改为4、6和8。没有重大变化

我正在考虑GC,但是我不能做很多事情来阻止它运行

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


另一方面,通过提高四叉树的树级,我获得了显著的性能改进。

因为您的段之间没有需要额外同步的依赖关系,所以我建议查看任务并行库TPL。Parallel.For或Parallel.ForEach可能会让您感兴趣

要优化现有代码,有几个选项:

删除TaskCreationOptions.LongRunning。它可能会产生新的线程,这非常耗时。 创建自己的任务调度器,并为底层线程提供更高的优先级。它也可以用于实验TPL并行循环。当前,您使用的是默认线程池,其他组件可能会使用/阻止该线程池。 更新:
另请参见如何创建具有不同优先级的自定义任务计划程序。它工作得非常好,我在几个项目中使用了它。另请参阅Stephen Toub的博客。

每个线程只能对单个物理核心进行utalize。也许这就是你所面临的。还有Task.WaitAlltasks;将仅在所有任务完成后继续,因此其中一些任务可能在所有任务完成之前已经完成。您需要提供一个。我们真的应该有代码,我们可以复制粘贴并运行以查看问题。理想情况下,我们也应该有一个非并行版本的代码,这样我们可以看到基本的计算是什么。不确定你的意图是什么,但你可以使它并行并检查。实现这一点的简单方法是使用并行for循环。您还可以设置处理器相关性,这同样取决于处理器核心。Enigmativity很遗憾,我不能提供一个最小的示例,因为代码在框架中运行,为了使其工作,我必须将一半的应用程序粘贴到这里。另外,我正在为一家公司开发这个应用程序,我不能分享太多的算法@Souvik otput必须是有序的,因此使用Parallel.For会使事情更加复杂,再加上创建一百万个委托的开销。然后我建议您创建异步函数任务,并在For循环中调用它们。因为您需要一个有序的for循环,所以我认为在循环的每次迭代中减少执行时间是很好的。