如何在多线程中填充一个数组?
How to fill an array in multiple threads?
有这样一个数组,通过Thread知道需要什么,但是不明白怎么做。您需要将数组拆分成多个部分,还是可以马上做一些事情?
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
int[] a = new int[10000];
Random rand = new Random();
for (int i = 0; i < a.Length; i++)
{
a[i] = rand.Next(-100, 100);
}
foreach (var p in a)
Console.WriteLine(p);
TimeSpan ts = stopWatch.Elapsed;
stopWatch.Stop();
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine("RunTime " + elapsedTime);
在现代 c# 中,您几乎不必使用 Thread
对象本身——它们充满了危险,还有其他语言功能也可以完成这项工作(请参阅 async
和 TPL)。我将向您展示一种使用 TPL 的方法。
注意:由于false sharing的问题,您需要设置一些东西,使不同的线程在不同的内存区域工作。否则您将看不到性能的提升——实际上,性能可能会变得相当糟糕。在此示例中,我将数组分成每个 4,000 字节(1,000 个元素)的块,并在单独的线程中处理每个块。
using System.Threading.Tasks;
var array = new int[10000];
var offsets = Enumerable.Range(0, 10).Select( x => x * 1000 );
Parallel.ForEach( offsets, offset => {
for ( int i=0; i<1000; i++ )
{
array[offset + i] = random.Next( -100,100 );
}
});
综上所述,我怀疑您是否会在这个示例中看到性能的提升——数组太小了,不值得额外的开销。
与 John Wu 的方法相比,另一种方法是使用自定义分区程序。我认为它更具可读性。
using System.Collections.Concurrent;
using System.Threading.Tasks;
int[] a = new int[10000];
int batchSize = 1000;
Random rand = new Random();
Parallel.ForEach(Partitioner.Create(0, a.Length, batchSize), range =>
{
for (int i = range.Item1; i < range.Item2; i++)
{
a[i] = rand.Next(-100, 100);
}
});
有这样一个数组,通过Thread知道需要什么,但是不明白怎么做。您需要将数组拆分成多个部分,还是可以马上做一些事情?
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
int[] a = new int[10000];
Random rand = new Random();
for (int i = 0; i < a.Length; i++)
{
a[i] = rand.Next(-100, 100);
}
foreach (var p in a)
Console.WriteLine(p);
TimeSpan ts = stopWatch.Elapsed;
stopWatch.Stop();
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine("RunTime " + elapsedTime);
在现代 c# 中,您几乎不必使用 Thread
对象本身——它们充满了危险,还有其他语言功能也可以完成这项工作(请参阅 async
和 TPL)。我将向您展示一种使用 TPL 的方法。
注意:由于false sharing的问题,您需要设置一些东西,使不同的线程在不同的内存区域工作。否则您将看不到性能的提升——实际上,性能可能会变得相当糟糕。在此示例中,我将数组分成每个 4,000 字节(1,000 个元素)的块,并在单独的线程中处理每个块。
using System.Threading.Tasks;
var array = new int[10000];
var offsets = Enumerable.Range(0, 10).Select( x => x * 1000 );
Parallel.ForEach( offsets, offset => {
for ( int i=0; i<1000; i++ )
{
array[offset + i] = random.Next( -100,100 );
}
});
综上所述,我怀疑您是否会在这个示例中看到性能的提升——数组太小了,不值得额外的开销。
与 John Wu 的方法相比,另一种方法是使用自定义分区程序。我认为它更具可读性。
using System.Collections.Concurrent;
using System.Threading.Tasks;
int[] a = new int[10000];
int batchSize = 1000;
Random rand = new Random();
Parallel.ForEach(Partitioner.Create(0, a.Length, batchSize), range =>
{
for (int i = range.Item1; i < range.Item2; i++)
{
a[i] = rand.Next(-100, 100);
}
});