【发布时间】:2018-04-05 23:09:31
【问题描述】:
我在尝试使用并行或任务计划或其他方式在 4 秒内完成工作时遇到问题。该脚本很简单,它会尝试一次处理 100 次并等待结果。我的电脑是 E5-2603 Xeon 处理器(4 核,4 线程,1.80GHz),16GB,处理 10000 个任务需要很长时间。
我可以做些什么来加快这个过程?
测试脚本
static void Main(string[] args)
{
//Monitor performance
Stopwatch totalTime = new Stopwatch();
//Test case # 1
totalTime.Start();
TaskTechnique();
totalTime.Stop();
Console.WriteLine("TaskTechnique total time: " + totalTime.Elapsed.TotalSeconds);
Console.WriteLine("--------------------------------------");
//Test case #2
totalTime.Reset();
totalTime.Start();
ParalelelTechnique();
totalTime.Stop();
Console.WriteLine("ParalelelTechnique total time: " + totalTime.Elapsed.TotalSeconds);
Console.WriteLine("--------------------------------------");
}
When Task Class Definition Namespace: System.Threading.Tasks
处理 100 个小任务需要 21 秒。代码如下
/// <summary>
/// Using task to process all tasks
/// </summary>
private static void TaskTechnique()
{
//Test case 1 process all 100 tasks at once
List<Task<string>> tasks = new List<Task<string>>();
for (int i = 0; i < 100; i++)
{
tasks.Add(
Task.Factory.StartNew
(
() =>
{
return MrDelay(i);
}
)
);
}
Task.WaitAll(tasks.ToArray());//Wait until finished
}
And when I used Parallel,处理时间为 33 秒。
/// <summary>
/// Using Paralelel to process 100 times
/// </summary>
private static void ParalelelTechnique()
{
//Monitor performance
Stopwatch startTime = new Stopwatch();
//Test case 2 using parallel
startTime.Restart();
int maxTask = 100;
var result = Parallel.For
(
1, 101,
new ParallelOptions { MaxDegreeOfParallelism = maxTask },
(i, state) =>
{
Console.WriteLine("Beginning iteration {0} at ", i, DateTime.Now.ToLocalTime());
string longTaskResult = MrDelay(i);
Console.WriteLine("Completed iteration {0} result at : {1}", i, longTaskResult);
}
);
startTime.Stop();
Console.WriteLine("test case 2: " + startTime.Elapsed.TotalSeconds);
}
延迟处理代码。
/// <summary>
/// Just to slow down the test to 3 seconds before return the data back
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
private static string MrDelay(int id)
{
//Delay 3 seconds then return the result
System.Threading.Thread.Sleep(3000);
return "ok request id: " + id.ToString() + " processed time: " + DateTime.Now.ToLocalTime();
}
【问题讨论】:
-
StartNew和Parallel.For都是专门为 CPU 限制 工作而设计的。如果您实际上没有 CPU 绑定的工作要做(在您的示例中您没有),它们将无法有效工作。如果您想创建一个将在 3 秒内完成的任务,请使用Task.Delay。 -
如果你想加快速度,你可以删除所有
Thread.Sleeps!你让工人睡觉,然后想知道他们为什么不工作! -
另外,做一些数学运算。你有 100 个任务。每个任务需要 3 秒的工作时间。您有四个核心,因此可以同时运行四个工作人员。所以每个核心有 25 个任务,所以大约需要 75 秒。你在 21 年就完成了工作,那你为什么抱怨呢?
-
正如 Servy 所说,这里的要点是:如果您正在执行 CPU 密集型工作,那么 您的测试需要实际对 CPU 施加压力,而不是睡眠,以便任务并行库可以有效地调度核心。如果您正在执行 IO 绑定工作,那么 您的测试应该将所有内容保存在一个线程上,并通过将等待放在正确的位置让编译器担心控制流。您创建了一个示例程序,它的所有内容都完全错误,因此得到垃圾结果也就不足为奇了。
-
对,如果您主要下载数据,那么并行化将无济于事;它会让情况变得更糟。 为您收到的每封邮件雇用一个人是否可以让您的邮件更快送达?当然不是。您只需要 一个 人在邮件到达时 进行分类。但是,如果你有一万份纳税申报表要准备,那么雇佣四名工人确实完成工作的速度是自己完成工作的四倍。 仅当核心饱和时才并行化工作。永远不要并行化等待 IO 事件的工作。