这是一个两部分的问题。
我已经编程确定了一系列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
}
}
我想根据处理器计数将此数字列表分为块,我可以从Environment.ProcessorCount
(通常是8(中获得,理想情况下,我最终会得到类似Tuples
的List
,其中每个Tuple
都包含在其中每个块的开始和最终值:
[(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())
};
一旦有了这个新的范围元素列表,我想将其中的每一个用作平行循环的基础,该基础在某些条件下写入ConcurrentDictionary
。我不确定如何将此代码纳入我的循环...
我已经在多个线程上使用了此代码,但是 2(我如何根据我在tupleList
中定义的范围均匀分发工作。>
var maxRateObj = new ConcurrentDictionary<string, double>();
var startTime = DateTime.Now;
Parallel.For(0,
stepsFromStartToMax,
new ParallelOptions
{
MaxDegreeOfParallelism = Environment.ProcessorCount
},
x =>
{
var i = (x * rateStep) + startRate;
Console.WriteLine("{0} : {1} : {2} ",
i,
DateTime.Now - startTime,
Thread.CurrentThread.ManagedThreadId);
if (!maxRateObj.Any())
{
maxRateObj["highestRateSoFar"] = i;
}
else {
if (i > maxRateObj["highestRateSoFar"])
{
maxRateObj["highestRateSoFar"] = i;
}
}
});
此打印出来,例如:
...
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需要处理第一个元组中的范围,螺纹2处理第二个元组中定义的范围,等等……在其中 i
由环路中的范围定义。同样,范围组的数量将取决于处理器的数量。谢谢。
我想根据处理器计数将此数字列表划分为块
LINQ Batch
方法有许多可能的实现。
您如何在较少的代码中选择内部范围,而不必知道我需要多少个元组?
这是处理此操作的一种方法:
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需要处理第一个元组中的范围,螺纹2处理第二个元组中定义的范围,等等...
...
除非您有一些困难要求某些线程处理某些批次,否则我强烈建议将您的作品作为单个"流"生成,并使用更高级别的抽象来进行并行性,例如plinq。
如果您只想在批处理工作,您仍然可以做到这一点,但不在乎正在完成的工作:
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());
}
默认的 TaskScheduler
正在为您的幕后协调工作,并且它可能会超越您自己的线程方案。
也考虑这样的东西:
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
...
*/