在 C# 中使用线程填充随机数的数组

Posted

技术标签:

【中文标题】在 C# 中使用线程填充随机数的数组【英文标题】:fill an array with random numbers using threads in c# 【发布时间】:2021-03-14 08:09:49 【问题描述】:

正如在图块中所说,我正在尝试使用 16 个(在我的情况下)线程填充一个带有随机数的字节数组,现在使用一个线程填充一个包含 500000000 个字节的数组大约需要六秒半的时间线程所以逻辑说使用 16 个线程将至少快 10 倍,但后来我尝试这样做,花了 15 秒来填充它,我所做的是我给每个线程一个段来填充相同的数组

代码如下:

        static byte[] nums2 = new byte[500000000];
        static Random rnd = new Random(123);
        static void fill()
        
            for (int i = 0; i < nums.Length; i++)
                nums[i] = (byte)rnd.Next(10);
        

        static void fillPart(object ID)
        
            var part = nums2.Length / Environment.ProcessorCount;
            int baseN = (int)ID * part;
            for (int i = baseN; i < baseN + part; i++)
                nums2[i] = (byte)rnd.Next(10);
            Console.WriteLine("Done! " + ID);
        

        static void Main(string[] args)
        
            Stopwatch watch = new Stopwatch();
            watch.Start();
            fill();
            watch.Stop();
            Console.WriteLine("it took " + watch.Elapsed);
            Console.WriteLine();

            watch.Reset();
            watch.Start();
            Thread[] threads = new Thread[Environment.ProcessorCount];
            for (int i = 0; i < Environment.ProcessorCount; i++)
            
                threads[i] = new Thread(fillPart);
                threads[i].Start(i);
            
            for(int i = 0; i < Environment.ProcessorCount; i++)
                threads[i].Join();

            watch.Stop();
            Console.WriteLine("it took " + watch.Elapsed);
        
    ```
would like to understand why is it took 15 seconds or maybe what I did wrong

【问题讨论】:

在多个线程中使用相同的Random 实例是不安全的。 哦,你说得对!它正在工作,只是在 fillpart 函数中添加了一个新的 Random 对象。我想知道为什么 现在的麻烦是您可能同时创建了一堆 Random 实例。为了使它们不会都喷出相同的数字,您将不得不进一步增加复杂性以确保它们以不同的方式播种。 这能回答你的问题吗? How to create byte array and fill it with random data 不,非常不!关键是使用线程@Sinatr 【参考方案1】:

如果是我,我会:

byte[] nums = new byte[500000000];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(nums);

并完成它。

如果你真的想要线程:

RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
var dop = 8;
var batchSize = 500000000 / dop;
var bigBytes = Enumerable.Range(0, dop).AsParallel().SelectMany(t => 
    var bytes = new byte[batchSize];
    rng.GetBytes(bytes); //This *IS* thread-safe
    return bytes;
).ToArray();

但我怀疑SelectManyToArray 整理到一个新数组所花费的时间可能会比单线程方法更昂贵。

【讨论】:

酷,我看不出你是如何工作的,也没有使用线程,但是很棒!【参考方案2】:

问题是你声明了static Random rnd = new Random(int.MaxValue); 如果您在fillPart 方法中创建Random 实例,那么程序将在一秒钟内完成,所以不是Thread 的问题是rnd.Next(10)

        static void fillPart(object ID)
                    
            Random rnd = new Random(123);

            var part = nums2.Length / Environment.ProcessorCount;
            int baseN = (int)ID * part;
            int co = 0;
            for (int i = baseN; i < baseN + part; i++)
            
                nums2[i] = (byte)rnd.Next(10);
            

            //Console.WriteLine("Done! " + ID + co);
        

【讨论】:

请参阅我上面关于播种 Random 的评论,以便生成的数组不会重复。 我认为他的问题不在于唯一编号,而在于线程性能。但你是对的,我受到了你的评论的启发

以上是关于在 C# 中使用线程填充随机数的数组的主要内容,如果未能解决你的问题,请参考以下文章

用随机数填充我的数组?

在 C# 中创建加密随机数的最快、线程安全的方法?

如何使用 for-loop if 语句填充具有唯一随机数的数组?

如何在 C# 数组字符串中选择 5 位随机数? [复制]

在 C# 中,如何在数组中存储随机数等于某些总和的次数?

随机数在数组c#中只有一次[重复]