gpt4 book ai didi

c# 并行与顺序

转载 作者:太空狗 更新时间:2023-10-29 19:39:26 25 4
gpt4 key购买 nike

我有一个很大的列表要循环(1.500.000 项),我必须对每个项目进行非常小的检查。总共 30 秒。

使用 Sequential 时的 CPU 使用率在 10% 左右,因此有很多资源未使用。

首先想到的是使用Parallel,但是由于每个item的持续时间有限,Parallel比顺序的Foreach持续的时间长,这是由于“Why was the parallel version slower than the sequential version in this example?”,说明创建每个task都会花费时间。

所以我有了另一个想法,那就是将列表分成 4 个(或更多)相等的和平,并创建一个线程来循环遍历项目以更快地获取它。

在创建我自己的类之前,这是一个好方法吗?或者关于如何加快速度的任何其他想法?或者您是否知道更好的处理方法。

代码

我为另一种并行方法创建的代码:(在我自己的静态类中使用)

public static void ForEach<T>(IEnumerable<T> list, Action<T> body, int listDevide)
{
// Number of items
int items = list.Count();
// Divided (in int, so floored)
int listPart = items / listDevide;
// Get numbers extra for last run
int rest = items % listDevide;

// List to save the actions
var actions = new List<Action>();
for(var x = 0; x < listDevide; x++)
{
// Create the actions
actions.Add(delegate {
foreach(var item in list.Skip(x * listPart).Take(listPart))
{
body.Invoke(item);
}
});
}

// Run the actions parallel
Parallel.Invoke(actions.ToArray());
}

备注:“rest”变量用于执行最后一项,当前未在此示例中使用。

下面的解决方案,更多信息:http://msdn.microsoft.com/en-us/library/dd997411.aspx

最佳答案

是的,对输入数组进行分区是一种很好的方法。

事实上,微软提供了一个Partitioner类来帮助实现这种方法。

这里有一个例子展示了如何做到这一点:

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;

namespace Demo
{
class Program
{
private void run()
{
double sum = 0;
Func<double, double> func = x => Math.Sqrt(Math.Sin(x));
object locker = new object();

double[] data = testData();

// For each double in data[] we are going to calculate Math.Sqrt(Math.Sin(x)) and
// add all the results together.
//
// To do this, we use class Partitioner to split the input array into just a few partitions,
// (the Partitioner will use knowledge about the number of processor cores to optimize this)
// and then add up all the values using a separate thread for each partition.
//
// We use threadLocalState to compute the total for each partition, and then we have to
// add all these together to get the final sum. We must lock the additon because it isn't
// threadsafe, and several threads could be doing it at the same time.

Parallel.ForEach
(
Partitioner.Create(0, data.Length),

() => 0.0,

(subRange, loopState, threadLocalState) =>
{
for (int i = subRange.Item1; i < subRange.Item2; i++)
{
threadLocalState += func(data[i]);
}

return threadLocalState;
},

finalThreadLocalState =>
{
lock (locker)
{
sum += finalThreadLocalState;
}
}
);

Console.WriteLine("Sum = " + sum);
}

private static double[] testData()
{
double[] array = new double[1000003]; // Test with an odd number of values.

Random rng = new Random(12345);

for (int i = 0; i < array.Length; ++i)
array[i] = rng.Next() & 3; // Don't want large values for this simple test.

return array;
}

static void Main()
{
new Program().run();
}
}
}

关于c# 并行与顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17469391/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com