0

我找到了两种从数组中获取 Max 值的不同方法,但我不太喜欢并行编程,所以我真的不明白。

我想知道这种方法是否也能做同样的事情,还是我错过了什么?我真的没有太多关于他们的信息。连评论都没有...

第一种方法:

int[] vec = ... (I guess the content doesn't matter)

static int naiveMax()
{
    int max = vec[0];
    object obj = new object();

    Parallel.For(0, vec.Length, i =>
    {
        lock (obj) {
                if (vec[i] > max) max = vec[i];
        }
    });

    return max;
}

第二个:

static int Max()
{
    int max = vec[0];
    object obj = new object();

    Parallel.For(0, vec.Length,     //could be Parallel.For<int>
        () => vec[0],
        (i, loopState, partial) =>
    {
        if(vec[i]>partial) partial = vec[i];
        return partial;
    },
    partial => {
            lock (obj) {
                    if( partial > max) max = partial;
            }
    });
    return max;
}

这些是做同样的事情还是做不同的事情?谢谢 ;)

4

2 回答 2

2

两者都在整数数组中找到最大值。为了更快地找到最大值,他们使用Parallel.For 方法“并行”进行。不过,这两种方法都失败了。

要看到这一点,我们首先需要一个足够大的整数数组。对于小型阵列,并行处理无论如何都不会给我们带来加速。

int[] values = new int[100000000];
Random random = new Random();
for (int i = 0; i < values.Length; i++)
{
    values[i] = random.Next();
}

现在我们可以运行这两种方法,看看它们需要多长时间。使用适当的性能测量设置(秒表、100,000,000 个整数的数组、100 次迭代、发布版本、未附加调试器、JIT 预热)我在我的机器上得到以下结果:

naiveMax   00:06:03.3737078
Max        00:00:15.2453303

所以Max比(6分钟!咳嗽好得多。naiveMax

但它与PLINQ相比如何?

static int MaxPlinq(int[] values)
{
    return values.AsParallel().Max();
}
MaxPlinq   00:00:11.2335842

不错,省了几秒。现在,用一个普通的、旧的、顺序for循环进行比较呢?

static int Simple(int[] values)
{
    int result = values[0];
    for (int i = 0; i < values.Length; i++)
    {
        if (result < values[i]) result = values[i];
    }
    return result;
}
Simple     00:00:05.7837002

我认为我们有一个赢家。

经验教训:Parallel.For不是你可以洒在代码上以使其神奇地运行得更快的小精灵。如果性能很重要,请使用正确的工具并测量,测量测量,...

于 2013-06-28T15:09:21.393 回答
0

他们似乎做同样的事情,但是他们非常低效。并行化的重点是提高可以独立执行的代码的速度。由于竞争条件,发现最大值(如在此处实现的)需要对实际逻辑进行原子信号量/锁定...这意味着您正在启动许多线程和相关资源只是为了按顺序执行代码...击败完全并行化的目的。

于 2013-06-28T15:10:10.847 回答