【问题标题】:Measure the Degree of Parallelism in TPL测量 TPL 中的并行度
【发布时间】:2012-11-13 06:34:22
【问题描述】:

任务并行库和 TPL 数据流允许指定最大并行度。该值是上限,而不是保证。实际上,TPL 将根据包括系统资源在内的许多因素确定实际并行度,而不会超过任何程序员指定的最大值。

是否有某种机制来确定 TPL 在某个时间点对并行度所做的选择?

我之所以这么问,是因为我移植了一些相当复杂的代码来使用 TPL Dataflow,而整体吞吐量远低于原始代码。我想看看 TPL 代表我做出了哪些选择,以了解它为什么慢得多。

【问题讨论】:

  • 我认为没有内置任何东西,但您应该可以通过添加自己的日志记录来做到这一点。
  • @svick:具体记录什么?我尝试创建一个托管线程 ID 的HashSet<int>,但发现MaximumDegreeOfParallelism 为 2 的事物最终会随着时间的推移在 5 个不同的线程上运行(无论如何这几乎是我的预期)。
  • 您可以在任务开始时增加一个计数器,然后在它完成时减少它。计数器的值将是当前的并行度,例如,您可能对它达到的最高值感兴趣。但它也可能更复杂。

标签: .net task-parallel-library


【解决方案1】:

我遇到了和你非常相似的情况。我最终使用我的日志数据来告诉我大致每分钟使用了多少线程。这给了我一个粗略但不准确的数字。

我不相信 TPL 可以为您提供有关其线程使用情况的遥测数据。如果你想实现更精确的东西,我建议在每个任务/线程中实现逻辑,以标记它开始时间和结束时间的一些共享列表。以下是我将如何着手开始的示例。

public class DoSomeTPLWork
{
    public static void Start()
    {
        List<int> numberList = Enumerable.Range(1, 1000).ToList();

        Parallel.ForEach(numberList, number =>
            {
                ThreadTracking.ThreadStarted();

                int square = number * number;
                Console.WriteLine("Square of {0} is {1}", number, square);

                ThreadTracking.ThreadFinished();
            }
        );

        var threadInfo = ThreadTracking.GetThreadInfo();
    }
}

public class ThreadTracking
{
    private static ConcurrentBag<ThreadInfo> _threadInfo = new ConcurrentBag<ThreadInfo>();

    public static void ThreadStarted()
    {
        var threadInfo = new ThreadInfo(Thread.CurrentThread.ManagedThreadId);
        threadInfo.Start();
        _threadInfo.Add(threadInfo);
    }

    public static void ThreadFinished()
    {
        var threadInfo = _threadInfo.Where(ti => ti.ThreadId == Thread.CurrentThread.ManagedThreadId && !ti.Complete).SingleOrDefault();
        if(threadInfo != null)
        {
            threadInfo.Stop();
        }
    }

    public static List<ThreadInfo> GetThreadInfo()
    {
        return _threadInfo.ToList();
    }
}

public class ThreadInfo
{
    public bool Complete { get; set; }
    public int ThreadId { get; set; }
    public DateTime? TimeStarted { get; set; }
    public DateTime? TimeFinished { get; set; }

    public ThreadInfo(int threadId)
    {
        ThreadId = threadId;
    }

    public void Start()
    {
        TimeStarted = DateTime.Now;
        Complete = false;
    }

    public void Stop()
    {
        TimeFinished = DateTime.Now;
        Complete = true;
    }
}

使用这些数据,您可以通过添加更多方法来查询数据或将其弹出到 Excel 中进行处理,从而查看在任何给定的秒数内使用了多少线程。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多