Parallel.Foreach +收益率回报?

Flo*_*ian 25 c# yield-return parallel.foreach

我想用这样的并行循环处理一些东西:

public void FillLogs(IEnumerable<IComputer> computers)
{
    Parallel.ForEach(computers, cpt=>
    {
        cpt.Logs = cpt.GetRawLogs().ToList();
    });

}
Run Code Online (Sandbox Code Playgroud)

好的,它工作正常.但是如果我想让FillLogs方法返回一个IEnumerable怎么办?

public IEnumerable<IComputer> FillLogs(IEnumerable<IComputer> computers)
{
    Parallel.ForEach(computers, cpt=>
    {
        cpt.Logs = cpt.GetRawLogs().ToList();
        yield return cpt // KO, don't work
    });

}
Run Code Online (Sandbox Code Playgroud)

编辑

似乎不可能......但我使用这样的东西:

public IEnumerable<IComputer> FillLogs(IEnumerable<IComputer> computers)
{
    return computers.AsParallel().Select(cpt => cpt);
}
Run Code Online (Sandbox Code Playgroud)

但是我把cpt.Logs = cpt.GetRawLogs().ToList();指示放在哪里

Mar*_*ell 14

短版本 - 不,这是通过迭代器块无法实现的; 较长的版本可能涉及调用者的迭代器线程(执行dequeue)和并行工作者(执行enqueue)之间的同步队列/出队; 但是作为旁注 - 日志通常是IO绑定的,并且对IO绑定的东西进行并行化通常不能很好地工作.

如果调用者需要花费一些时间来消耗每个,那么一次只处理一个日志的方法可能有一些优点,但是调用者使用前一个日志时可以这样做; 也就是说,它开始一个Task 下一个项目之前yield,和之后的等待完成yield...但是,这又是,相当复杂.作为简化示例:

static void Main()
{
    foreach(string s in Get())
    {
        Console.WriteLine(s);
    }
}

static IEnumerable<string> Get() {
    var source = new[] {1, 2, 3, 4, 5};
    Task<string> outstandingItem = null;
    Func<object, string> transform = x => ProcessItem((int) x);
    foreach(var item in source)
    {
        var tmp = outstandingItem;

        // note: passed in as "state", not captured, so not a foreach/capture bug
        outstandingItem = new Task<string>(transform, item);
        outstandingItem.Start();

        if (tmp != null) yield return tmp.Result;
    }
    if (outstandingItem != null) yield return outstandingItem.Result;
}
static string ProcessItem(int i)
{
    return i.ToString();
}
Run Code Online (Sandbox Code Playgroud)


Fis*_*aen 5

我不想冒犯,但也许缺乏理解。Parallel.ForEach意味着TPL将根据可用硬件在多个线程中运行foreach。但这意味着,ii 可以并行完成这项工作!yield return让您有机会从列表(或任何其他)中获取一些值,并在需要时将它们一一返回。它无需首先查找与条件匹配的所有项目,然后迭代它们。这确实是性能优势,但无法并行完成。

  • 但是,如果每一代yield 返回值都需要一定的时间,那么您是否会希望并行处理下一个yield 返回值,以便更快地获得它。我想有一个缓冲区什么的?我不知道是否缺乏理解,但我可以想象(即使有理解)人们想要更快地屈服的情况。我猜yield的目的是在必要时进行处理,所以yield return可能并不严格适合。但我当然可以想象想要的是什么...... (3认同)