C#并行和任务太慢
我有一个问题,试图在4秒内完成工作,无论是使用并行或任务时间表或任何东西。这个脚本很简单,它将尝试一次处理100次,然后等待结果。我的电脑是E5-2603 Xeon处理器(4核,4线程,1.80GHz),16GB,它花了很长时间才能处理100个任务 我可以做些什么来加快这个过程 测试脚本C#并行和任务太慢,c#,parallel-processing,C#,Parallel Processing,我有一个问题,试图在4秒内完成工作,无论是使用并行或任务时间表或任何东西。这个脚本很简单,它将尝试一次处理100次,然后等待结果。我的电脑是E5-2603 Xeon处理器(4核,4线程,1.80GHz),16GB,它花了很长时间才能处理100个任务 我可以做些什么来加快这个过程 测试脚本 static void Main(string[] args) { //Monitor performance Stopwatch totalTi
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("--------------------------------------");
}
处理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
}
//
///使用任务处理所有任务
///
私有静态void tasktechnology()
{
//测试用例1一次处理所有100个任务
列表任务=新列表();
对于(int i=0;i<100;i++)
{
任务。添加(
Task.Factory.StartNew
(
() =>
{
返回延迟(i);
}
)
);
}
Task.WaitAll(tasks.ToArray());//等待完成
}
,处理过程耗时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);
}
//
///采用并行处理100次
///
专用静态空隙并行技术()
{
//监控性能
秒表开始时间=新秒表();
//使用并行测试的测试用例2
startTime.Restart();
int-maxTask=100;
var result=Parallel.For
(
1, 101,
新的并行选项{MaxDegreeOfParallelism=maxTask},
(一、州)=>
{
WriteLine(“开始迭代{0}”,i,DateTime.Now.ToLocalTime());
字符串longTaskResult=MrDelay(i);
WriteLine(“在:{1}处完成的迭代{0}结果”,i,longTaskResult);
}
);
开始时间。停止();
WriteLine(“测试用例2:+startTime.passed.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();
}
//
///在返回数据之前,将测试速度减慢到3秒
///
///
///
专用静态字符串MrDelay(int-id)
{
//延迟3秒,然后返回结果
系统线程线程睡眠(3000);
返回“确定请求id:+id.ToString()+”处理时间:“+DateTime.Now.ToLocalTime()”;
}
对于大众服务代码,您必须首先回答以下问题:最大值应该是多少
例如,使用任务意味着“最大吞吐量”。这意味着您的任务可能会经常被中断,等待某些东西,所以让CPU核心切换到另一个任务以避免浪费时间。每个任务的平均执行时间相对较长,但每个给定时间内处理的任务量却在飞速增长
这里的另一个例子是“最大CPU消耗”。例如,这些员工喜欢处理音频/视频流、大型数学工厂,比如加密等。这样,最有效的方法是每个备用CPU核心有一个线程/任务,而不是更多(因为切换到另一个线程会花费额外的CPU工作)。与前一个示例相反,这里我们在给定时间内处理的平均任务量相对较低。但由于中断最少,平均执行时间尽可能短
当然,在实际操作中,你有一些东西介于这两个最大值之间。当然,您必须更多地了解哪些因素会影响您的CPU(内核调用、缓存污染、错误共享、数据竞争等等)。您可以从《无bug兔子》中的精彩文章开始:感谢您的提示,我提出了另一个使用多线程的解决方案。此应用程序将在桌面应用程序上使用,因此这是可以接受的。我能够在3秒内使用线程处理200个或更多任务,而不是100个任务处理30秒以上
static void Main(string[] args)
{
#region MyRegion
for (int i = 0; i < 200; i++)
{
//Create thread
Thread thread = new Thread(() => DoBigJobThread(i));
thread.Start();
}
#endregion
//Slow down to show screen
System.Threading.Thread.Sleep(3000000);
}
static void DoBigJobThread(int id)
{
Console.WriteLine(MrDelaySimple(id));
}
private static string MrDelaySimple(int id)
{
//Delay 3 seconds
System.Threading.Thread.Sleep(3000);
return "ok request id: " + id.ToString() + " processed time: " + DateTime.Now.ToLocalTime();
}
static void Main(字符串[]args)
{
#区域MyRegion
对于(int i=0;i<200;i++)
{
//创建线程
线程线程=新线程(()=>DoBigJobThread(i));
thread.Start();
}
#端区
//放慢速度以显示屏幕
系统线程线程睡眠(3000000);
}
静态无效DoBigJobThread(内部id)
{
Console.WriteLine(MrDelaySimple(id));
}
私有静态字符串MrDelaySimple(int-id)
{
//延迟3秒
系统线程线程睡眠(3000);
返回“确定请求id:+id.ToString()+”处理时间:“+DateTime.Now.ToLocalTime()”;
}
StartNew和Parallel.For
都是专门为CPU受限的工作而设计的。如果您实际上没有CPU绑定的工作要做(在您的示例中,您没有这样做),它们将无法有效地工作。如果要创建一个将在3秒内完成的任务,请使用task.Delay
。如果要加速,可以删除所有线程。Sleeps
!你让工人睡觉,然后想知道他们为什么不工作!另外,做一些数学。你有100个任务。每个任务需要3秒的工作时间。您有四个核心,因此四个工人可以同时运行。每个核心有25个任务,所以大约需要75秒。你在21世纪就完成了任务,那你为什么要抱怨呢?正如Servy所说,这里的要点是:如果你在做CPU限制的工作,那么你的测试实际上需要强调CPU,而不是睡眠,这样任务并行库就可以有效地调度核心。如果您正在执行IO绑定的工作,那么您的测试应该将所有内容保持在一个线程上,并通过将等待放在正确的位置让编译器担心控制流。你已经做了一个示例程序,它做的每件事都是完全错误的,因此得到垃圾结果也就不足为奇了