测量TPL中的并行度

4

任务并行库(Task Parallel Library)和TPL数据流允许指定最大并行度。该值是一个上限,而不是保证。实际上,TPL将根据多种因素(包括系统资源)确定实际的并行度,同时不超过任何程序员指定的最大值。

有没有一种机制可以确定TPL在某个时间点所做出的并行度选择?

我之所以这样问,是因为我将一些相当复杂的代码移植到了使用TPL数据流,而整体吞吐量要比原始代码低得多。我想查看TPL代表我的选择来理解为什么速度要慢得多。


我认为没有内置的功能,但是您应该能够通过添加自己的日志记录来实现这一点。 - svick
@svick:记录什么?我尝试创建一个HashSet<int>来管理线程ID,但发现具有最大并行度为2的任务最终会在5个不同的线程上运行(这基本上是我预期的)。 - Eric J.
当任务开始时,您可以递增一个计数器,然后在任务完成时递减它。计数器的值将是当前并行度,例如您可能对其达到的最高值感兴趣。但它也可能是更复杂的东西。 - svick
1个回答

3
我遇到了和你很相似的情况。我最终使用我的日志数据告诉我每分钟大概有多少线程被使用。这给了我一个粗略的数字,但不是准确的。
我认为 TPL 不能提供有关其线程使用情况的遥测信息。如果您想实现更准确的内容,我建议在每个 Task/Thread 中实现逻辑来标记一些共享列表,记录其开始和结束时间。以下是我开始时处理此问题的示例。
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进行操作,了解任何给定秒钟正在使用多少线程。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接