C#并行。用于减少循环执行时间
我找到了一台osrm机器,当我请求时它返回一个json字符串。json有一些关于2位置的特殊信息,我正在处理json并获取distance属性的值,用于构建这些位置的距离矩阵。我有2000多个地点,这个过程大约需要4个小时。我需要通过并行性来减少执行时间,但我对这个主题还很陌生。这是我的工作,我应该如何优化并行循环?或者你可以开车送我到新的方法。谢谢C#并行。用于减少循环执行时间,c#,json,multithreading,parallel.for,C#,Json,Multithreading,Parallel.for,我找到了一台osrm机器,当我请求时它返回一个json字符串。json有一些关于2位置的特殊信息,我正在处理json并获取distance属性的值,用于构建这些位置的距离矩阵。我有2000多个地点,这个过程大约需要4个小时。我需要通过并行性来减少执行时间,但我对这个主题还很陌生。这是我的工作,我应该如何优化并行循环?或者你可以开车送我到新的方法。谢谢 var client = new RestClient("http://127.0.0.1:5000/route/v1/table/");
var client = new RestClient("http://127.0.0.1:5000/route/v1/table/");
var watch = System.Diagnostics.Stopwatch.StartNew();
//rawCount = 2500
Parallel.For(0, rowCount, i =>
{
Parallel.For(0, rowCount, j =>
{
//request a server with spesific lats,longs
var request = new RestRequest(String.Format("{0},{1};{2},{3}", le.LocationList[i].longitude, le.LocationList[i].latitude,
le.LocationList[j].longitude, le.LocationList[j].latitude));
//reading the response and deserialize into object
var response = client.Execute<RootObject>(request);
//defining objem with the List of attributes in routes
var objem = response.Data.routes;
//this part reading all distances and durations in each response and take them into dist and dur matrixes.
Parallel.ForEach(objem, (o) =>
{
dist[i, j] = o.distance;
dur[i, j] = o.duration;
threads[i,j] = Thread.CurrentThread.ManagedThreadId;
Thread.Sleep(10);
});
});
});
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
var client=new RestClient(“http://127.0.0.1:5000/route/v1/table/");
var watch=System.Diagnostics.Stopwatch.StartNew();
//原始计数=2500
Parallel.For(0,rowCount,i=>
{
Parallel.For(0,行计数,j=>
{
//请求具有特定lats、longs的服务器
var request=new RestRequest(String.Format(“{0},{1};{2},{3}”),le.LocationList[i]。经度,le.LocationList[i]。纬度,
le.LocationList[j].经度,le.LocationList[j].纬度);
//读取响应并反序列化为对象
var response=client.Execute(请求);
//使用管线中的属性列表定义objem
var objem=response.Data.routes;
//这一部分读取每个响应中的所有距离和持续时间,并将它们放入dist和dur矩阵中。
Parallel.ForEach(objem,(o)=>
{
距离[i,j]=o.距离;
dur[i,j]=o.持续时间;
threads[i,j]=Thread.CurrentThread.ManagedThreadId;
睡眠(10);
});
});
});
看,停;
var elapsedMs=watch.elapsedmillisons;
我把它清理了一下。一次使用并行就足够了。还有一个循环,你需要看看,因为它正在覆盖数据,我不知道该怎么处理它,那就是你的调用
您需要稍微体验一下maxThreads
变量的值。通常,.NET会启动足够多的线程,以便处理器能够处理它们,在您的情况下,您可以启动更多线程,因为您知道所有线程都在空闲等待网络堆栈
using System;
using System.Linq;
using System.Threading.Tasks;
namespace ConsoleApp7
{
class Program
{
static void Process(int i, int j)
{
var client = new RestClient("http://127.0.0.1:5000/route/v1/table/");
//request a server with spesific lats,longs
var request = new RestRequest(String.Format("{0},{1};{2},{3}", le.LocationList[i].longitude, le.LocationList[i].latitude, le.LocationList[j].longitude, le.LocationList[j].latitude));
//reading the response and deserialize into object
var response = client.Execute<RootObject>(request);
//defining objem with the List of attributes in routes
var objem = response.Data.routes;
//this part reading all distances and durations in each response and take them into dist and dur matrixes.
// !!!
// !!! THIS LOOP NEEDS TO GO.
// !!! IT MAKES NO SENSE!
// !!! YOU ARE OVERWRITING YOUR OWN DATA!
// !!!
Parallel.ForEach(objem, (o) =>
{
dist[i, j] = o.distance;
dur[i, j] = o.duration;
threads[i, j] = Thread.CurrentThread.ManagedThreadId;
Thread.Sleep(10);
});
}
static void Main(string[] args)
{
var watch = System.Diagnostics.Stopwatch.StartNew();
var rowCount = 2500;
var maxThreads = 100;
var allPairs = Enumerable.Range(0, rowCount).SelectMany(x => Enumerable.Range(0, rowCount).Select(y => new { X = x, Y = y }));
Parallel.ForEach(allPairs, new ParallelOptions { MaxDegreeOfParallelism = maxThreads }, pair => Process(pair.X, pair.Y));
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
}
}
}
使用系统;
使用System.Linq;
使用System.Threading.Tasks;
名称空间控制台App7
{
班级计划
{
静态无效过程(inti,intj)
{
var client=新的RestClient(“http://127.0.0.1:5000/route/v1/table/");
//请求具有特定lats、longs的服务器
var request=new-RestRequest(String.Format(“{0},{1};{2},{3}”,le.LocationList[i]。经度,le.LocationList[i]。纬度,le.LocationList[j]。经度,le.LocationList[j]。纬度));
//读取响应并反序列化为对象
var response=client.Execute(请求);
//使用管线中的属性列表定义objem
var objem=response.Data.routes;
//这一部分读取每个响应中的所有距离和持续时间,并将它们放入dist和dur矩阵中。
// !!!
//!!!这个循环需要结束。
//!!!这毫无意义!
//!!!您正在覆盖您自己的数据!
// !!!
Parallel.ForEach(objem,(o)=>
{
距离[i,j]=o.距离;
dur[i,j]=o.持续时间;
threads[i,j]=Thread.CurrentThread.ManagedThreadId;
睡眠(10);
});
}
静态void Main(字符串[]参数)
{
var watch=System.Diagnostics.Stopwatch.StartNew();
var行数=2500;
var maxThreads=100;
var allPairs=Enumerable.Range(0,rowCount).SelectMany(x=>Enumerable.Range(0,rowCount).Select(y=>new{x=x,y=y});
ForEach(allPairs,newparalleloptions{MaxDegreeOfParallelism=maxThreads},pair=>Process(pair.X,pair.Y));
看,停;
var elapsedMs=watch.elapsedmillisons;
}
}
}
线程睡眠(10)的作用是什么?如果你想减慢代码的速度,告诉你的线程睡眠就可以了,所以这可能是这里的问题。而嵌套并行。For
也可能不是一个好主意。开销太大了。只需将其用于最外层的循环。Parallel.ForEach
应该做什么,在每次迭代中将信息写入相同的数据存储?我在mvc4框架上工作,我无法实现您的方法。另一方面,我心里也有一些问题。在循环中可以看到超过2000x2000(4m)次迭代。我想将for-loop部分划分为max线程,每个卡盘应该只驱动1个线程。因此,它们在同一时间进行处理,并且不能覆盖其他人的工作。我怎样才能使用parallel.for函数呢?您也说过,我在循环部分中过度使用了数据。怎样?你能解释一下吗?thanks@EmreG循环将写入数据:dist[i,j]=o.distance代码>,但i
和j
不会改变。所有路由距离都将写入阵列的同一单元格中。最后一条路线获胜。至于你剩下的问题:你应该把并行化留给Parallel。对于每个人来说,它比你知道的要复杂得多。在我的解决方案中,您有一个2500*2500循环,.NET运行时决定如何使它在您的机器上尽可能快地运行。