【问题标题】:Parallel.For vs for loopParallel.For 与 for 循环
【发布时间】:2016-03-09 18:03:37
【问题描述】:

我正忙于运行并行线程,因此我决定在较小的基础上对其进行测试,然后在我感到舒服时进行扩展。我将同样的过程与自己相提并论;一个使用 Parallel.For,另一个使用基本的 for 循环。我正在捕捉时间(以刻度为单位)进行比较。示例代码采用一个数组(在本例中为 53 个两个字符串)并用该数组填充给定的ListBox。

对我来说几乎没有意义的是,当我运行基本的 For 循环时,它平均产生 1,400 个滴答声,但是当我运行 Parallel.For 循环时,它平均返回 5,200 个滴答声。样本量是否太小而无法并行有效?

这是我正在使用的两个 sn-ps。 Parallel.For 循环是:

public void ListboxFromArray(ListBox listbox, string[] array1)
{
    // This method takes an array and fills a listbox full of items from the array
    Stopwatch stopWatch = new Stopwatch();
    stopWatch.Start();

    Parallel.For(0, array1.Count(),
    index =>
    {
        listbox.Items.Add(array1[index]);
    });
    stopWatch.Stop();
    long ts = stopWatch.ElapsedTicks;
    string elapsedTime = ts.ToString() + " Ticks"; ;
    MessageBox.Show(elapsedTime);

}

for 循环是:

public void ListboxFromArray(ListBox listbox, string[] array1)
{
    // This method takes an array and fills a listbox full of items from the array
    Stopwatch stopWatch = new Stopwatch();
    stopWatch.Start();

    for (int i = 0; i < array1.Count(); i++)
    {
        listbox.Items.Add(array1[i]);
    }
    stopWatch.Stop();
    long ts = stopWatch.ElapsedTicks;
    string elapsedTime = ts.ToString() + " Ticks"; ;
    MessageBox.Show(elapsedTime);
}

感谢您提前输入或验证我的想法。

【问题讨论】:

  • 除了执行时间之外,您可能还想查看列表框项目的最终顺序。最好的情况是它们将处于与数组无关的随机半不匹配顺序。最坏的情况是,如果列表框不是线程安全的,它将做未定义的事情。除了仅用于高 CPU 情况外,您还应该尝试保留 Parallel 以供项目执行不完全依赖于一个中心对象时使用。 (这可能意味着将来合并结果)

标签: c# for-loop parallel.for


【解决方案1】:

如果您想为集合中的每个项目计算需要一些时间来计算的东西,则使用 Parallel.For 很有用。

int[] coll = new int[]{10,9,8,7,6,5,4,3,2,1};

Parallel.ForEach(coll,
    item=>
    {
       Thread.Sleep(TimeSpan.FromSeconds(item));
       Console.WriteLine(item + "Finished");
    });

与顺序方式相比

foreach (var item in coll)
{
    Thread.Sleep(TimeSpan.FromSeconds(item));
    Console.WriteLine(item + "Finished");
}

第一个代码运行得更快,因为它确实是并行工作的。

在您的情况下,如果您只想执行“无工作”,那么thead 的开销太大了。

【讨论】:

    【解决方案2】:

    我不认为你可以这样做......首先,你正在从非 UI 线程访问 UI 控件 (ListBox)。 AFAIK,Parallel.For 没有进行任何线程编组以确保安全。其次,您正在从多个线程访问同一个集合 (ListBox.Items) 而没有锁定 - 同样不安全。

    一般来说,我会说这不是Parallel.For 的用途。此处的 I/O 或 CPU 并没有完全成为瓶颈,这意味着任何并行开销都会使任何可能的改进相形见绌。

    【讨论】:

    • 我实际上并没有在用途上不同意您的观点,我更多的是要求我自己对彼此之间所涉及的过程的理解有所启发。谢谢。
    【解决方案3】:

    我认为您的样本量太小,而且您在循环中所做的工作太小,无法克服任务/线程管理的开销。并行一个消耗如此少 CPU 的内存中的操作没有什么意义。如果您要对 100,000 个项目进行排序,那么也许...

    【讨论】:

    • 谢谢,这就是困扰我的原因。我不是 100% 确定,但这对我来说也是最有意义的,我只是想要第二个意见。
    • 其实这是错误的。他的样本量并不算小——他的代码不是线程安全的。另外,我操纵了一个 UI 控件,该控件不支持多线程,因此如果它工作,它会通过自动将其编组到一个线程来工作。完全无聊的测试。
    • @TomTom - Items 只是一个 ListBoxObjectCollection,它不是线程安全的(除非明确设计为这样,否则没有集合),但这不会影响他的测试性能。同意 Add 的结果可能不是任何定义的顺序(但这是 Parallel.For 所期望的),这不是一个真实的例子,但由于他没有遇到异常,因此允许他访问集合 - 除非您认为 Parallel.ForEach 正在“注意到”对控件的跨线程访问,然后是单线程 .... 我认为这不太可能。一个糟糕的测试,但是......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    • 1970-01-01
    • 1970-01-01
    • 2021-01-09
    • 2020-07-10
    • 1970-01-01
    相关资源
    最近更新 更多