C#4中的并行随机播放?

时间:2010-08-29 19:43:20

标签: c# parallel-processing

在这个问题中注意到:Randomize a List<T>你可以在列表上实现一个shuffle方法;像其中一个答案提到:

using System.Security.Cryptography;
...
public static void Shuffle<T>(this IList<T> list)
{
    RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
    int n = list.Count;
    while (n > 1)
    {
        byte[] box = new byte[1];
        do provider.GetBytes(box);
        while (!(box[0] < n * (Byte.MaxValue / n)));
        int k = (box[0] % n);
        n--;
        T value = list[k];
        list[k] = list[n];
        list[n] = value;
    }
}

有人知道是否可以使用C#4中的一些新功能“并行”这个?

只是好奇心。

全心全意,

-R

3 个答案:

答案 0 :(得分:1)

任何就地shuffle都不太适合并行化。特别是因为随机播放需要一个随机分量(超出范围),所以无法定位部分问题。

答案 1 :(得分:1)

好吧,你可以很容易地并行化生成随机数的代码 - 当使用加密安全随机数生成器时,可能成为瓶颈。然后,您可以在执行交换的单个线程中使用该序列的随机数(需要保留其顺序)。

我刚刚遇到的一个问题是,RNGCryptoServiceProvider不是线程安全的(System.Random也不是)。你需要尽可能多的随机数生成器作为线程来完成这项工作。基本上它变得有点难看:(

答案 2 :(得分:1)

您的问题不明确,但您可以使用并行框架来帮助并行执行某些操作,但这取决于您是否要获取字节,然后将它们随机播放,因此获取字节是并行的,或者,如果你想一次洗牌多个名单。

如果是前者,我建议您首先将代码分解为更小的函数,这样您就可以进行一些分析,看看瓶颈在哪里,如果获取字节是瓶颈,那么就这样做吧并行可能会有所作为。通过测试,您可以测试新功能并确定是否值得增加复杂性。

static RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();

private static byte[] GetBytes() {
        byte[] box = new byte[1];
        do provider.GetBytes(box);
        while (!(box[0] < n * (Byte.MaxValue / n)));
        return box;
}
private static IList<T> InnerLoop(int n, IList<T> list) {
        var box = GetBytes(n);
        int k = (box[0] % n);
        T value = list[k];
        list[k] = list[n];
        list[n] = value;
        return list;
}

public static void Shuffle<T>(this IList<T> list)
{
    int n = list.Count;
    while (n > 1)
    {
        list = InnerLoop(n, list);
        n--;
    }
}

关于如何拆分函数,这是一个粗略的想法,因此您可以替换GetBytes函数,但您可能需要进行一些其他更改来测试它。

获取一些数字对于确保获得足够的利益以保证增加复杂性至关重要。

您可能希望将处理InnerLoop的{​​{1}}中的行移动到一个单独的函数中,这样您就可以看到它是否很慢并且可能会换出一些算法来改进它,但是,你需要知道你需要多快的整个洗牌操作。

但是如果你想做多个列表那么这很容易,你可能想看看list

<强>更新

上面的代码只是为了展示如何将其分解为更小的功能,不是一个有效的解决方案。如果有必要将我放入静态变量的Provider类移动到一个函数中,然后将其作为参数传递,那么可能需要完成。我没有测试代码,但我的建议是基于获取分析然后看看如何提高它的性能,特别是因为我不确定它是什么意思并行完成。可能有必要按顺序构建一个数组,然后将它们混合,然后首先看看每个操作所需的时间,然后看看是否需要并行执行。

如果使用多个线程,可能还需要使用并发数据结构,以便不必通过必须自己同步来支付罚金,但是,根据瓶颈的位置,可能不再需要这样做。

<强>更新

根据我的评论的答案,您可能希望查看并行库中的各种功能,但此页面可能会有所帮助。 http://msdn.microsoft.com/en-us/library/dd537609.aspx

您可以创建函数的PLINQ版本,并将其作为参数传递。使用此库有多种方法可以并行执行此功能,因为您已经没有任何全局变量,只需丢失Func运算符。

你会想要在添加更多线程时获取数字,看看你开始看到性能下降的地方,因为你不会看到1:1的改进,所以,如果你添加2个线程就赢了“ t快两倍,所以只需测试并查看哪里有更多线程的问题。由于你的函数是CPU绑定的,你可能希望每个核心只有一个线程,作为一个粗略的起点。