【发布时间】:2018-02-06 06:54:53
【问题描述】:
考虑以下代码 sn-p 并注意将 numberTasksToSpinOff 设置为 1 和 3,4 或更多(取决于您机器上的线程资源)之间的总运行时间差异。我注意到在拆分更多任务时运行时间要长得多。
我故意将数据集合传递到每个工作人员任务同时读取的每个工作人员实例中。我认为只要这些操作只是读取或枚举,任务就可以访问共享数据结构而不会阻塞。
我的目标是分拆多个任务,这些任务通过读取操作在相同的共享数据结构上进行迭代,并在大约同一时间完全完成,而不管分拆的任务数量是多少。
编辑:请查看我实现Parallel.Foreach() 的第二个代码 sn-p 并创建每个工作人员自己的数据集,因此不同任务/线程不会访问相同的数据结构。然而,我仍然看到不可接受的开销。
class Program
{
static void Main(string[] args)
{
Console.WriteLine($"Entry Main Function Thread Id: {Thread.CurrentThread.ManagedThreadId}");
//run
var task = Task.Run(async () =>
{
Console.WriteLine($"Entry RunMe Task Thread Id: {Thread.CurrentThread.ManagedThreadId}");
await RunMe();
Console.WriteLine($"Exit RunMe Task Thread Id: {Thread.CurrentThread.ManagedThreadId}");
});
task.Wait();
Console.WriteLine($"Exit Main Function Thread Id: {Thread.CurrentThread.ManagedThreadId}");
Console.WriteLine("Press key to quit");
Console.ReadLine();
}
private static async Task RunMe()
{
var watch = new Stopwatch();
var numberTasksToSpinOff = 6;
var numberItems = 20000;
var random = new Random((int)DateTime.Now.Ticks);
var dataPoints = Enumerable.Range(1, numberItems).Select(x => random.NextDouble()).ToList();
var tasks = new List<Task>();
var workers = new List<Worker>();
//structure workers
for (int i = 1; i <= numberTasksToSpinOff; i++)
{
workers.Add(new Worker(i, dataPoints));
}
//start timer
watch.Restart();
//spin off tasks
foreach (var worker in workers)
{
tasks.Add(Task.Run(() =>
{
Console.WriteLine($"Entry WorkerId: {worker.WorkerId} -> New Tasks spun off with in Thread Id: {Thread.CurrentThread.ManagedThreadId}");
worker.DoSomeWork();
Console.WriteLine($"Exit WorkerId: {worker.WorkerId} -> New Tasks spun off with in Thread Id: {Thread.CurrentThread.ManagedThreadId}");
}));
}
//completion tasks
await Task.WhenAll(tasks);
//stop timer
watch.Stop();
Console.WriteLine($"Time it took to complete in Milliseconds: {watch.ElapsedMilliseconds}");
}
}
public class Worker
{
public int WorkerId { get; set; }
private List<double> _data;
public Worker(int workerId, List<double> data)
{
WorkerId = workerId;
_data = data;
}
public void DoSomeWork()
{
var indexPos = 0;
foreach (var dp in _data)
{
var subSet = _data.Skip(indexPos).Take(_data.Count - indexPos).ToList();
indexPos++;
}
}
}
第二个代码片段:
class Program
{
static void Main(string[] args)
{
var watch = new Stopwatch();
var numberTasksToSpinOff = 1;
var numberItems = 20000;
//var random = new Random((int)DateTime.Now.Ticks);
//var dataPoints = Enumerable.Range(1, numberItems).Select(x => random.NextDouble()).ToList();
var workers = new List<Worker>();
//structure workers
for (int i = 1; i <= numberTasksToSpinOff; i++)
{
workers.Add(new Worker(i));
}
//start timer
watch.Restart();
//parellel work
if (workers.Any())
{
var processorCount = Environment.ProcessorCount;
var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = processorCount };
Parallel.ForEach(workers, parallelOptions, DoSomeWork);
}
//stop timer
watch.Stop();
Console.WriteLine($"Time it took to complete in Milliseconds: {watch.ElapsedMilliseconds}");
Console.WriteLine("Press key to quit");
Console.ReadLine();
}
private static void DoSomeWork(Worker worker)
{
Console.WriteLine($"WorkerId: {worker.WorkerId} -> New Tasks spun off with in Thread Id: {Thread.CurrentThread.ManagedThreadId}");
var indexPos = 0;
foreach (var dp in worker.Data)
{
var subSet = worker.Data.Skip(indexPos).Take(worker.Data.Count - indexPos).ToList();
indexPos++;
}
}
}
public class Worker
{
public int WorkerId { get; set; }
public List<double> Data { get; set; }
public Worker(int workerId)
{
WorkerId = workerId;
var numberItems = 20000;
var random = new Random((int)DateTime.Now.Ticks);
Data = Enumerable.Range(1, numberItems).Select(x => random.NextDouble()).ToList();
}
}
【问题讨论】:
-
你有没有做过任何事情来调试这个?您的问题中没有证据表明您已经尝试解释您的观察结果。使用分析器,找出所有时间都花在了哪里。我敢打赌你会发现它是垃圾收集器,因为你的任务做的主要事情是创建 lot 的垃圾。
-
@PeterDuniho,是的,我已经调试了代码,我什至在代码中打印了线程 ID。你是不正确的,即使我只是迭代数据结构而不创建任何额外的数据,我看到总执行时间同样爆炸。在这种情况下,我发现您的“近距离投票”在没有首先澄清的情况下过分了。如果我已经弄清楚了,我就不会发布问题了。我认为这正是这个网站的用途。不是每个人都可能在此时拥有与您相同的知识,因此寻求建议。
-
这似乎是一个合理的问题,对我来说有一些合理的辩论......不知道为什么它被关闭,特别是如果可能找到解决方案?
标签: c# multithreading task task-parallel-library