当前位置: 首页 > wzjs >正文

傻瓜式网站建设软件金融类网站建设

傻瓜式网站建设软件,金融类网站建设,uniapp微信小程序模板,杭州互联网公司排名探讨如何加快 C# 双循环的速度效率 一、前言二、多种循环的速度效率2.1、常用循环速度效率对比2.2、如何提高循环的速度效率2.2.1、选择合适的循环类型2.2.2、减少循环体内的操作2.2.3、使用局部变量而非频繁访问成员2.2.4、避免在循环体内进行不必要的对象创建或销毁2.2.5、仅…

探讨如何加快 C# 双循环的速度效率

  • 一、前言
  • 二、多种循环的速度效率
    • 2.1、常用循环速度效率对比
    • 2.2、如何提高循环的速度效率
      • 2.2.1、选择合适的循环类型
      • 2.2.2、减少循环体内的操作
      • 2.2.3、使用局部变量而非频繁访问成员
      • 2.2.4、避免在循环体内进行不必要的对象创建或销毁
      • 2.2.5、仅当适用时可采用并行处理
  • 三、如何提高双循环计算速度效率的编程实例
    • 3.1、中规中矩的双循环
    • 3.2、采用改进二分法的双循环
    • 3.3 、采用并行循环
  • 四、双循环更好的办法

一、前言

最近使用 C# 改写以前编的一个程序,检索数据赋值时,使用 FOR 循环结构,当数据量在9万条时,计算量很大,导致很耗时,何况计算完成同时加载到 chart 和 dataGridView 图表控件中(没有使用第三方控件),于是百度了很多循环手段。

二、多种循环的速度效率

2.1、常用循环速度效率对比

循环结构体速度和效率
for(int i=0;i<n;i++){}对于已知次数的迭代,使用 for 循环通常是最快的。
foreach(string S in Data){}适用于遍历集合,如数组或列表,但通常比 for 循环慢,因为它需要更多的间接访问。
while
do-while
适用于不确定次数的迭代,但可能在性能上不如 for 循环。
Parallel.For
Parallel.ForEach
Parallel.Invoke
并行计算类,三个方法都会阻塞线程直到所有工作完成为止。仅当适用时可采用,否则出现意外错误。
Parallel.ForEach 比 Parallel.For 效率更高。
Parallel.Invoke 适合用于执行大量且无返回值的场景;
Parallel.For 使用是无序的,适合带索引的大量循环操作;
Parallel.ForEach 适合数组、集合、枚举大数据集的循环执行,执行结果是无序的。

2.2、如何提高循环的速度效率

2.2.1、选择合适的循环类型

循环的效率通常取决于多个因素,包括循环的类型、循环体内的操作、以及循环的次数。选择合适的循环类型很重要。

2.2.2、减少循环体内的操作

循环体内的操作越少,循环的效率越高。例如,避免在每次迭代中进行复杂的计算或方法调用。

2.2.3、使用局部变量而非频繁访问成员

如果循环体内需要多次访问对象的成员,最好将该成员的值存储在局部变量中,这样可以减少多次访问成员的开销。

2.2.4、避免在循环体内进行不必要的对象创建或销毁

每次迭代创建新对象会增加GC(垃圾回收)的压力,降低性能。如果可能,考虑对象池技术或复用对象。

2.2.5、仅当适用时可采用并行处理

对于可以并行处理的计算任务,使用 Parallel.For 或 PLINQ(Parallel LINQ)可以显著提高性能,特别是当处理大量数据时。然而,并行处理需要谨慎使用,因为它会增加线程管理的开销。

三、如何提高双循环计算速度效率的编程实例

遵循上述循环原则,对于有序的数据集,通过多次测试各种循环,采用的 for 双循环。

Hypack RAW 数据中,实时采集的定位 POS 数据和 EC1 数据系列,时间和位置大部分不同步,但处于同一个航线轨迹上,通过各采集点的时间秒、坐标、水深,计算航行距离、航行速度,以计算插补 EC1 采集数据所在定位坐标。

POS 数据有时间、定位东和北坐标数组,POSTime[]、POSEast[]、POSNorth[] 数据长度一致。
EC1 数据有时间、水深数组,EC1Time[]、EC1WaterDepth[] 数据长度一致。

POS 和 EC1 数据个数不对等。

还要根据 FIX 和 EC1 数据,插补 FIX 采集数据点的水深,这里就不描述。

Hypack RAW 数据节选如下:

POS 0 37410.599 626291.650 3216635.552
QUA 0 37410.599 7 3.000 1.000 8.000 2.000 0.000 0.000 0.000
RAW 0 37410.599 4 290361.17840 1121780.82570 9.91600 22330.60000
MSG 0 37410.538 $GPGGA,022330.60,2903.611784,N,11217.808257,E,2,08,1.0,9.916,M,0.0,M,8.0,0643*71
MSG 0 37410.581 $GPVTG,22.3,T,,M,0.08,N,0.15,K,P*23
MSG 0 37410.600 $GPZDA,022330.60,27,03,2024,00,00*62
EC1 1 37410.736 1.040
POS 0 37410.799 626291.660 3216635.561
QUA 0 37410.799 7 3.000 1.000 8.000 2.000 0.000 0.000 0.000
RAW 0 37410.799 4 290361.17890 1121780.82630 9.90800 22330.80000
MSG 0 37410.735 $GPGGA,022330.80,2903.611789,N,11217.808263,E,2,08,1.0,9.908,M,0.0,M,8.0,0643*7A
MSG 0 37410.778 $GPVTG,42.9,T,,M,0.15,N,0.27,K,P*22
MSG 0 37410.797 $GPZDA,022330.80,27,03,2024,00,00*6C
EC1 1 37410.939 1.040
POS 0 37411.000 626291.673 3216635.574
QUA 0 37411.000 7 3.000 1.000 8.000 2.000 0.000 0.000 0.000
RAW 0 37411.000 4 290361.17960 1121780.82710 9.89800 22331.00000
MSG 0 37410.938 $GPGGA,022331.00,2903.611796,N,11217.808271,E,2,08,1.0,9.898,M,0.0,M,8.0,0643*76
MSG 0 37410.981 $GPVTG,46.0,T,,M,0.17,N,0.31,K,P*2A
MSG 0 37411.001 $GPZDA,022331.00,27,03,2024,00,00*65
FIX 99 37411.109 48 626291.673 3216635.574
EC1 1 37411.138 1.030
POS 0 37411.200 626291.687 3216635.584
QUA 0 37411.200 7 3.000 1.000 8.000 2.000 0.000 0.000 0.000
RAW 0 37411.200 4 290361.18010 1121780.82800 9.90800 22331.20000
MSG 0 37411.137 $GPGGA,022331.20,2903.611801,N,11217.808280,E,2,08,1.0,9.908,M,0.0,M,4.0,0643*7F
MSG 0 37411.180 $GPVTG,54.9,T,,M,0.21,N,0.39,K,P*2D
MSG 0 37411.199 $GPZDA,022331.20,27,03,2024,00,00*67
EC1 1 37411.337 1.020
POS 0 37411.400 626291.708 3216635.595
QUA 0 37411.400 7 3.000 1.000 8.000 2.000 0.000 0.000 0.000
RAW 0 37411.400 4 290361.18070 1121780.82930 9.90400 22331.40000
MSG 0 37411.336 $GPGGA,022331.40,2903.611807,N,11217.808293,E,2,08,1.0,9.904,M,0.0,M,4.0,0643*71
MSG 0 37411.379 $GPVTG,57.9,T,,M,0.23,N,0.42,K,P*20
MSG 0 37411.398 $GPZDA,022331.40,27,03,2024,00,00*61
EC1 1 37411.538 1.030
POS 0 37411.599 626291.727 3216635.606
QUA 0 37411.599 7 3.000 1.000 8.000 2.000 0.000 0.000 0.000
RAW 0 37411.599 4 290361.18130 1121780.83050 9.90100 22331.60000
MSG 0 37411.537 $GPGGA,022331.60,2903.611813,N,11217.808305,E,2,08,1.0,9.901,M,0.0,M,4.0,0643*7D
MSG 0 37411.580 $GPVTG,61.7,T,,M,0.22,N,0.41,K,P*29
MSG 0 37411.600 $GPZDA,022331.60,27,03,2024,00,00*63
EC1 1 37411.737 1.020
POS 0 37411.799 626291.750 3216635.618
QUA 0 37411.799 7 3.000 1.000 8.000 2.000 0.000 0.000 0.000
RAW 0 37411.799 4 290361.18190 1121780.83190 9.89600 22331.80000
MSG 0 37411.736 $GPGGA,022331.80,2903.611819,N,11217.808319,E,2,08,1.0,9.896,M,0.0,M,4.0,0643*7B
MSG 0 37411.779 $GPVTG,64.7,T,,M,0.25,N,0.45,K,P*2F
MSG 0 37411.798 $GPZDA,022331.80,27,03,2024,00,00*6D
EC1 1 37411.937 1.030
POS 0 37412.000 626291.774 3216635.627
QUA 0 37412.000 7 3.000 1.000 8.000 2.000 0.000 0.000 0.000
RAW 0 37412.000 4 290361.18240 1121780.83340 9.89900 22332.00000
MSG 0 37411.937 $GPGGA,022332.00,2903.611824,N,11217.808334,E,2,08,1.0,9.899,M,0.0,M,4.0,0643*7E
MSG 0 37411.980 $GPVTG,68.6,T,,M,0.25,N,0.47,K,P*20
MSG 0 37411.999 $GPZDA,022332.00,27,03,2024,00,00*66
EC1 1 37412.138 1.020
POS 0 37412.200 626291.790 3216635.646

3.1、中规中矩的双循环

以下代码实例中,是 Hypack RAW 数据处理中的双循环,插补 EC1 采集数据所在定位坐标。
数据的时间秒从小到大有序排列。

	 for (int j = 0; j < POSLeng; j++){if (j == 0 && EC1Time[i] < POSTime[j])//EC1时间小于第一个POS时间{EC1East[i] = POSEast[j] - (POSEast[j + 1] - POSEast[j]) / (POSTime[j + 1] - POSTime[j]) * (POSTime[j] - EC1Time[i]);//水深点东坐标EC1North[i] = POSNorth[j] - (POSNorth[j + 1] - POSNorth[j]) / (POSTime[j + 1] - POSTime[j]) * (POSTime[j] - EC1Time[i]);//水深点北坐标break;}if (j == POSLeng - 1 && EC1Time[i] > POSTime[POSLeng - 1])//EC1时间大于最后一个POS时间{EC1East[i] = POSEast[j] + (POSEast[j] - POSEast[j - 1]) / (POSTime[j] - POSTime[j - 1]) * (EC1Time[i] - POSTime[j]);//水深点东坐标EC1North[i] = POSNorth[j] + (POSNorth[j] - POSNorth[j - 1]) / (POSTime[j] - POSTime[j - 1]) * (EC1Time[i] - POSTime[j]);//水深点北坐标break;}if (EC1Time[i] == POSTime[j]){EC1East[i] = POSEast[j];EC1North[i] = POSNorth[j];break;}if ((EC1Time[i] > POSTime[j]) && (EC1Time[i] < POSTime[j + 1])){EC1East[i] = POSEast[j] + (POSEast[j + 1] - POSEast[j]) / (POSTime[j + 1] - POSTime[j]) * (EC1Time[i] - POSTime[j]);//水深点东坐标EC1North[i] = POSNorth[j] + (POSNorth[j + 1] - POSNorth[j]) / (POSTime[j + 1] - POSTime[j]) * (EC1Time[i] - POSTime[j]);//水深点北坐标break;}}SurveyEC1[i, 0] = EC1Time[i];SurveyEC1[i, 1] = EC1East[i];SurveyEC1[i, 2] = EC1North[i];SurveyEC1[i, 3] = EC1WaterDepth[i];

以上代码循环效率不高,测试中,当 RAW 文件 3119 KB,EC1 数据量达到 97981 个,POS数据量达到 6142 个,FIX数据量达到 503个。插补 EC1 采集点的坐标和 从 EC1 采集点检索 FIX 采集的水深,很耗时,达到 2 千毫秒左右,插补数据后,还要加载到 chart 和 dataGridView 图表控件中,加载图标达到 7 百毫秒左右,导致显示很慢。

3.2、采用改进二分法的双循环

为了提高运算速度和效率,采用改进二分法的双循环,根据循环原则,优化代码结构,使用类封装坐标计算循环为 InterpCoord 函数,二分法循环调用它。插补 EC1 采集点的坐标和 FIX 采集的水深,整体循环减小到 764 毫秒左右。

  //根据 POS 定位数据和时间数据,以航速计算插补 EC1 水深的定位坐标//改进二分法,加快循环int EC1Leng = ListEc1Time.Length;//EC1数据个数int MedianNum = 0;if ((EC1Leng & 1) == 0){MedianNum = EC1Leng / 2;//偶数,数据半数}else{MedianNum = (int)(EC1Leng / 2) + 1; //奇数,数据半数+1}for (int i = 0; i <= MedianNum; i++)//for (int i = 0; i < EC1Leng; i++){//从时间秒最小索引 i = 0 开始顺序计算到中数InterpCoord(EC1Time[i], ref EC1East[i], ref EC1North[i], POSTime, POSEast, POSNorth);SurveyEC1[i, 0] = EC1Time[i];SurveyEC1[i, 1] = EC1East[i];SurveyEC1[i, 2] = EC1North[i];SurveyEC1[i, 3] = EC1WaterDepth[i];//从时间秒最大索引 i = EC1Leng - 1 开始逆序计算到中数int ReverseOrderNum = EC1Leng - i - 1;InterpCoord(EC1Time[ReverseOrderNum], ref EC1East[ReverseOrderNum], ref EC1North[ReverseOrderNum], POSTime, POSEast, POSNorth);//组合为二维 EC1 数据SurveyEC1[ReverseOrderNum, 0] = EC1Time[ReverseOrderNum];SurveyEC1[ReverseOrderNum, 1] = EC1East[ReverseOrderNum];SurveyEC1[ReverseOrderNum, 2] = EC1North[ReverseOrderNum];SurveyEC1[ReverseOrderNum, 3] = EC1WaterDepth[ReverseOrderNum];}

使用类封装坐标计算循环为 InterpCoord 函数,以便构造引用:

 public class Hypack{/// <summary>计算 EC1 时间点的坐标</summary>/// <param name="InterpTime">EC1时间点</param>/// <param name="InterpEast">EC1东坐标</param>/// <param name="InterpNorth">EC1西坐标</param>/// <param name="LineTime">POS时间点</param>/// <param name="LineEast">POS东坐标</param>/// <param name="LineNorth">POS西坐标</param>public static void InterpCoord(double InterpTime, ref double InterpEast, ref double InterpNorth, double[] LineTime, double[] LineEast, double[] LineNorth){int LineLeng = LineTime.Length;if (InterpTime < LineTime[0])//EC1时间小于第一个 POS 线上时间,计算EC1时间对应坐标{InterpEast = LineEast[0] - (LineEast[1] - LineEast[0]) / (LineTime[1] - LineTime[0]) * (LineTime[0] - InterpTime);//水深点东坐标InterpNorth = LineNorth[0] - (LineNorth[1] - LineNorth[0]) / (LineTime[1] - LineTime[0]) * (LineTime[0] - InterpTime);//水深点北坐标}else if (InterpTime > LineTime[LineLeng - 1])//EC1时间大于最后一个 POS 线上时间,计算EC1时间对应坐标{InterpEast = LineEast[LineLeng - 1] + (LineEast[LineLeng - 1] - LineEast[LineLeng - 2]) / (LineTime[LineLeng - 1] - LineTime[LineLeng - 2]) * (InterpTime - LineTime[LineLeng - 1]);//水深点东坐标InterpNorth = LineNorth[LineLeng - 1] + (LineNorth[LineLeng - 1] - LineNorth[LineLeng - 2]) / (LineTime[LineLeng - 1] - LineTime[LineLeng - 2]) * (InterpTime - LineTime[LineLeng - 1]);//水深点北坐标}else{for (int j = 0; j < LineLeng; j++){if (InterpTime == LineTime[j])//EC1时间等于 POS 线上时间,坐标一致{InterpEast = LineEast[j];InterpNorth = LineNorth[j];break;}if ((InterpTime > LineTime[j]) && (InterpTime < LineTime[j + 1]))//EC1时间在 POS 线上 2 个时间之间,计算EC1时间对应坐标{InterpEast = LineEast[j] + (LineEast[j + 1] - LineEast[j]) / (LineTime[j + 1] - LineTime[j]) * (InterpTime - LineTime[j]);//水深点东坐标InterpNorth = LineNorth[j] + (LineNorth[j + 1] - LineNorth[j]) / (LineTime[j + 1] - LineTime[j]) * (InterpTime - LineTime[j]);//水深点北坐标break;}}}// 尝试如下代码更耗时,相当于增加了循环,尽管代码简洁 找到大于目标的第一个元素的索引//int indexGreaterThan = Array.FindIndex(LineTime, n => n > InterpTime); 找到等于于target的第一个元素的索引//int indexEqualThan = Array.FindIndex(LineTime, n => n == InterpTime); 找到小于target的第一个元素的索引//int indexLessThan = Array.FindLastIndex(LineTime, n => n < InterpTime);//if (indexEqualThan >= 0)//{//    InterpEast = LineEast[indexEqualThan];//    InterpNorth = LineNorth[indexEqualThan];//}//if (indexLessThan >= 0 && indexGreaterThan >= 0)//{//    InterpEast = LineEast[indexLessThan] + (LineEast[indexGreaterThan] - LineEast[indexLessThan]) / (LineTime[indexGreaterThan] - LineTime[indexLessThan]) * (InterpTime - LineTime[indexLessThan]);//水深点东坐标//    InterpNorth = LineNorth[indexLessThan] + (LineNorth[indexGreaterThan] - LineNorth[indexLessThan]) / (LineTime[indexGreaterThan] - LineTime[indexLessThan]) * (InterpTime - LineTime[indexLessThan]);//水深点北坐标//}}
}

3.3 、采用并行循环

为了提高到更快的运算速度和效率,采用并行循环,优化代码结构,调用类封装的坐标计算循环为 InterpCoord 函数。插补 EC1 采集点的坐标和 FIX 采集的水深,整体循环减小到 377 毫秒左右。

   Parallel.For(0, EC1Leng, j =>{InterpCoord(EC1Time[j], ref EC1East[j], ref EC1North[j], POSTime, POSEast, POSNorth);SurveyEC1[j, 0] = EC1Time[j];SurveyEC1[j, 1] = EC1East[j];SurveyEC1[j, 2] = EC1North[j];SurveyEC1[j, 3] = EC1WaterDepth[j];});

四、双循环更好的办法

多线程处理不当容易内存溢出,线程间的错误处理和同步问题。需要严谨的避免多个线程同时访问同一资源,否则导致冲突或错误。‌存在内存销毁消耗,处理不当反而浪费时间,增加开销。其它方法还在探索中…

你有更好的建议吗?

http://www.dtcms.com/wzjs/582505.html

相关文章:

  • 科技资讯网站开发大纲女性手机网站模板
  • 如何提升网站的收录量携程特牌 的同时做别的网站
  • 建设网站租用空间wordpress删除相似文章
  • ps如何做游戏模板下载网站贵州省建设厅网站
  • 广东官网网站建设品牌黑龙江省住房和城乡建设部网站
  • 云南手机网站开发wordpress 动态主题
  • 自己做企业网站服务器网站建设代理成本
  • 建设永久网站自己做的网站怎么调用百度地图
  • 中国文化网站建设策划书企业网上书店网站建设设计
  • 洛阳酒店网站开发大全临沂做网站推广的公司
  • 哪个网站查食品建设好wordpress 总站模板
  • 做淘宝客必须建网站吗高端html5网站建设织梦模板 dedecms5.7织梦网络公司源
  • 珠海公司网站制作几级分销是合法的
  • 网络软营销自己给网站做优化怎么做
  • 双峰做网站网站后台统计
  • 甘露园网站建设网站备案查询 站长
  • 为了找工作做的前端网站怎么看网站有没有被收录
  • 渭南房产网站制作wordpress通过api发送邮件
  • 企业网站 管理食品营销网站建设调查问卷
  • 广州各类外贸网站制作网站的模板
  • 设计网站都有什么作用是什么天津平台公司
  • html5手机微网站模板wordpress 排除指定分类
  • 网站建设天猫店淘宝哪些做网站关键词排名的有用吗
  • 长沙网站建设公司名单东莞人才市场现场招聘会地址
  • 做百度手机网站优化快百度软件开放平台
  • 互联网行业招聘网站免费下载的网页模板
  • 做纪念品网站wordpress免费的企业主题
  • 品牌网站建设特色wordpress新用户管理
  • wordpress 翻墙河南网站建设优化
  • 做设计常用的网站网站建设实训设备