C# 选择“相等”;“块”;从并行for循环的IEnumerable范围
这是一个由两部分组成的问题 我已通过编程确定了一系列C# 选择“相等”;“块”;从并行for循环的IEnumerable范围,c#,multithreading,parallel-processing,C#,Multithreading,Parallel Processing,这是一个由两部分组成的问题 我已通过编程确定了一系列double值: public static void Main(string[] args) { var startRate = 0.0725; var rateStep = 0.001; var maxRate = 0.2; var stepsFromStartToMax = (int)Math.Ceiling((maxRate-startRate)/rateS
double
值:
public static void Main(string[] args)
{
var startRate = 0.0725;
var rateStep = 0.001;
var maxRate = 0.2;
var stepsFromStartToMax = (int)Math.Ceiling((maxRate-startRate)/rateStep);
var allRateSteps = Enumerable.Range(0, stepsFromStartToMax)
.Select(i => startRate + (maxRate - startRate) * ((double)i / (stepsFromStartToMax - 1)))
.ToArray();
foreach (var i in allRateSteps)
{
Console.WriteLine(i); // this prints the correct values
}
}
我想根据处理器计数将此数字列表划分为多个块,我可以从环境中获得处理器计数。ProcessorCount
(通常为8)。理想情况下,我会以元组的列表
结束,其中每个元组
包含每个块的起始值和结束值:
[(0.725, 0.813), (0.815, 0.955), ...]
1)如何在不知道需要多少元组的情况下,用更少的代码选择内部范围?我想出了一个很长的方法来处理循环,但我希望LINQ能在这里提供帮助:
var counter = 0;
var listOne = new List<double>();
//...
var listEight = new List<double>();
foreach (var i in allRateSteps)
{
counter++;
if (counter < allRateSteps.Length/8)
{
listOne.Add(i);
}
//...
else if (counter < allRateSteps.Length/1)
{
listEight.Add(i);
}
}
// Now that I have lists, I can get their First() and Last() to create tuples
var tupleList = new List<Tuple<double, double>>{
new Tuple<double, double>(listOne.First(), listOne.Last()),
//...
new Tuple<double, double>(listEight.First(), listEight.Last())
};
这会打印出来,例如:
...
0.1295 : 00:00:00.4846470 : 5
0.0825 : 00:00:00.4846720 : 8
0.1645 : 00:00:00.4844220 : 6
0.0835 : 00:00:00.4847510 : 8
...
Thread1需要处理第一个元组中的范围,thread2处理第二个元组中定义的范围,等等。。。其中,i
由循环中的范围定义。同样,范围元组的数量将取决于处理器的数量。谢谢
我想根据处理器计数将这个数字列表分成几块
对于LINQ批处理
方法,有以下几种方法
如何在不需要知道需要多少元组的情况下,以更少的代码选择出内部范围
这里有一种处理方法:
var batchRanges = from batch in allRateSteps.Batch(anyNumberGoesHere)
let first = batch.First()
let last = batch.Last()
select Tuple.Create(first, last);
(0.0725, 0.0795275590551181)
(0.0805314960629921, 0.0875590551181102)
(0.0885629921259842, 0.0955905511811024)
...
如何根据我在tupleList
示例的这一部分没有引用tupleList,因此很难看到所需的行为
Thread1需要处理第一个元组中的范围,thread2处理第二个元组中定义的范围,等等
除非您对某些线程处理某些批处理有严格要求,否则我强烈建议您将工作生成为单个“流”,并使用更高级别的并行抽象,例如
如果您只想成批完成工作,您仍然可以这样做,但不关心在哪个线程上完成工作:
static void Work(IEnumerable<int> ints) {
var sum = ints.Sum();
Thread.Sleep(sum);
Console.WriteLine(ints.Sum());
}
public static void Main (string[] args) {
var inputs = from i in Enumerable.Range(0, 100)
select i + i;
var batches = inputs.Batch(8);
var tasks = from batch in batches
select Task.Run(() => Work(batch));
Task.WaitAll(tasks.ToArray());
}
站点上有许多用于批处理w/LINQ的现有Q&a,但是创建批处理以手动跨核心进行调度可能是不必要的,并且性能不如让一个代理为您处理。为什么不创建自己的线程
s,并让每个进程都有自己的输入列表?@TaylorWood-您可以在此上下文中动态创建可变数量的线程吗?是的,您可以创建动态大小的线程集合,但为什么不在线程池中使用任务呢?这部分令人困惑:“如何在不知道需要多少元组的情况下,以更少的代码选择出内部范围?“从问题的其余部分来看,你似乎在处理已知的数量和输入。为什么你不知道你需要多少元组?@ScottHannen-我想用LINQ来获取n
部分中的批,其中n=Environment.ProcessorCount
。我在我的代码中硬编码了8个处理器的假设,因为我没有办法显示优化的方式(我还不知道),感谢这个伟大的答案。我只是意识到,我实际上不需要将要完成的工作“划分”为某种数据结构,如listuple
,然后将其提供给并行函数,因为“划分要完成的工作”并将其分布在线程中正是使用这种方法的目的。
static void Work(IEnumerable<int> ints) {
var sum = ints.Sum();
Thread.Sleep(sum);
Console.WriteLine(ints.Sum());
}
public static void Main (string[] args) {
var inputs = from i in Enumerable.Range(0, 100)
select i + i;
var batches = inputs.Batch(8);
var tasks = from batch in batches
select Task.Run(() => Work(batch));
Task.WaitAll(tasks.ToArray());
}
static int Work(IEnumerable<int> ints) {
Console.WriteLine("Work on thread " + Thread.CurrentThread.ManagedThreadId);
var sum = ints.Sum();
Thread.Sleep(sum);
return sum;
}
public static void Main (string[] args) {
var inputs = from i in Enumerable.Range(0, 100)
select i + i;
var batches = inputs.Batch(8);
var tasks = from batch in batches
select Work(batch);
foreach (var task in tasks.AsParallel()) {
Console.WriteLine(task);
}
}
/*
Work on thread 6
Work on thread 4
56
Work on thread 4
184
Work on thread 4
Work on thread 4
312
440
...
*/