WinRT开发的功能和效率

这里我选择运行计算复杂度较高的算法作为测试方法,虽然不能代表全部,但 是很大程度上展示大家平时开发过程中所面临的常见场景 和问题。考虑到演示和 理解,就选择了查找100000以内的所有素数的个数的算法作为演示。另外也顺带演 示如何在WinRT下实现多编程语言和技 术之间的协作吧。

商州网站建设公司成都创新互联公司,商州网站设计制作,有大型网站制作公司丰富经验。已为商州千余家提供企业网站建设服务。企业网站搭建\成都外贸网站建设公司要多少钱,请找那个售后服务好的商州做网站的公司定做!

关于基本知识和算法吧详细的说明,请自行搜索各大引擎吧(关键 词:prime、素数),这里我就列举在各个语言下我的简单实现吧,其中包括使用 普通算法和并 行计算的两个版本。

***部分,从目前.NET主流来看吧,以C# 为例,普通版本,这个没什么多说的,就是从前往后看某个数是不是素数:

 
 
 
  1. private static int
  2. CountingInternal(int n)
  3. {
  4.      var numprimes = 1;
  5.      for (var i = 3; i <= n; i += 2)
  6.      {
  7.          var isPrime = true;
  8.          var limit = Math.Ceiling(Math.Sqrt(i)) + 1;
  9.          for (var j = 3; j < limit; j += 2)
  10.          {
  11.              if (i%j == 0)
  12.              {
  13.                  isPrime = false;
  14.                  break;
  15.              }
  16.          }
  17.          if (isPrime)
  18.          {
  19.              numprimes++;
  20.          }
  21.      }
  22.      return numprimes;
  23. }

并行版本稍微复杂一点点,选择Parallel.For来并行执行一个从1至n/2的并行 循环(我这里偷懒了一下,没有处理奇 偶数的情况,因为我的调用时传入的都是 偶数),发现是素数,使用Interlocked辅助方法给计数增加1。

 
 
 
  1. private static int
  2. CountingParallel(int n)
  3. {
  4.      var numprimes = 1;
  5.      Parallel.For(1, n/2, i =>
  6.      {
  7.          if (IsPrime(i*2 + 1))
  8.          {
  9.               Interlocked.Increment(ref numprimes);
  10.          }
  11.      });
  12.      return numprimes;
  13. }
  14.  
  15. public static bool IsPrime(int n)
  16. {
  17.      if (n%2 == 0)
  18.          return false;
  19.      var limit = (int) (Math.Ceiling(Math.Sqrt(n)) + 1);
  20.      for (var i = 3; i < limit; i += 2)
  21.      {
  22.          if (n%i == 0)
  23.          {
  24.              return false;
  25.          }
  26.      }
  27.      return true;
  28. }

***种场景,直接嵌入算法到C# WinRT App工程,执行结果如下(单位毫 秒):

执行次数 1(启动) 2 3 4 5
普通 14.0299 9.0005 9.1825 8.0021 11.0181
并行 6.0008 2.0004 2.9993 2.0014 3.999

第二种场景,将C#算法包装在一个类库里(注意 是CLR类库,只能在C#/VB直接通用),在C# WinRT App工程中调用这个类库,执行 结果如下(单位毫秒):

执行次数 1(启动) 2 3 4 5
普通 12.0299 9.0019 10.003 9.0014 9.00017
并行 6.0008 2 3.0003 2.9997 1.9995

第三种场景,将C#算法包装到一个Windows Runtime Component(WRC)中,在C# WinRT App工程中调用这个WRC类库,执行结 果如下(单位毫秒):

执行次数  1(启动)  2 3 4
普通  11.9904  9.0032  9  9。0028 9.00149 
并行   6.0008  1.9817  1.9985  1.9993  2

第四种场景,将C#算法包装到一个Windows Runtime Component(WRC)中,在WinJS App工程中调用这个WRC类库,执行结果如 下(单位毫秒):

执行次数  1(启动)  2 3 4
普通  11  9  8  9 8
并行   4  1  1  3  2

小结:以上是从.NET角度来进行的比较,很容易 看出***次CLR加载在这里性能损耗表现的很明显,完成加载之后性能将稳定在一 定范 围内波动;另外,并行计算在纯算法的应用中有很明显的性能优势。

第二部分,接下来我们回归Native环境,这里我 依然使用普通和并行计算两种来尝试,普通的依然没什么可说的(实际上和C#的没 区 别,除了关键字不一样)。

  
 
 
  1. static int CountingInternal(int n)
  2. {
  3.      auto numprimes = 1;
  4.      for (auto i = 3; i <= n; i += 2)
  5.      {
  6.          auto isPrime = true;
  7.          auto limit = ceil(sqrt(i)) + 1;
  8.  
  9.          for (auto j = 3; j < limit; j += 2)
  10.          {
  11.              if (i%j == 0)
  12.              {
  13.                  isPrime = false;
  14.                  break;
  15.              }
  16.          }
  17.  
  18.          if (isPrime)
  19.          {
  20.              numprimes++;
  21.          }
  22.      }
  23.      return numprimes;
  24. }

并行版本,需要注意的是C++ lambda的传值 和作用域问题,其他的和C#的没区别:

  
 
 
  1. static bool IsPrime(int n)
  2. {
  3.      if (n%2 == 0)
  4.          return false;
  5.      auto limit = (int) (ceil(sqrt(n)) + 1);
  6.      for(auto i=3; i
  7.      {
  8.          if(n%i == 0)
  9.          {
  10.              return false;
  11.          }
  12.      }
  13.      return true;
  14. }
  15.  
  16. static int CountingParallel(int n)
  17. {
  18.      auto numprimes = 1;
  19.      parallel_for(1, n/2, [&](int i)
  20.      {
  21.          if(IsPrime(i*2+1))
  22.          {
  23.              InterlockedIncrement((volatile unsigned long*)&numprimes);
  24.          }
  25.      });
  26.      return numprimes;
  27. }

***种场景,直接将C++算法放到C++ WinRT App 中使用,执行结果如下(单位毫秒):

执行次数  1(启动)  2 3 4
普通  8.0019 7.9991  8.0209  8.9843  8.0181 
并行   1.9794  1.998  1.9994  1.984  2.0003

第二种场景,将C++算法包装在DLL中,在C++ WinRT App中使用,执行结果如下(单位毫秒):

执行次数  1(启动)  2 3 4
普通  9 9  9  8  9 
并行   3 2  3  2  2

第三种场景,将C++算法包装在动态连接库Dll中,在C# WinRT App中通过 PInvoke来调用,执行结果如下(单位毫秒):

执行次数  1(启动)  2 3 4
普通  9 9  8  9  9 
并行   3 2  3  2  3

第四种场景,将C++算法包装在静态链接库Lib中,在C++ WinRT App中调用,执 行结果如下(单位毫秒):

执行次数  1(启动)  2 3 4
普通  8 8  8  9  9 
并行   2 3  3  2  3

第五种场景,将C++算法包装在Windows Runtime Component(WRC)中,在C# WinRT App中调用,执行结果如下(单位毫秒):

执行次数  1(启动)  2 3 4
普通  8.0014 8.0191  8.0293  8.0019  9.0291
并行   1.9994 1.9999  1.998  1.9994  2.99982

第六种场景,将Windows Runtime Component(WRC)中,在WinJS App中调用, 执行结果如下(单位毫秒):

执行次数  1(启动)  2 3 4
普通  9 8  9  8  8 
并行   2 2  3  2  3

第七种场景是将C++算法包装在Windows Runtime Library(WRL,基于COM的底 层开发)中,然后在任何一种WinRT App中调用,可以预见这是一种很强大的方 式,但同时也是最费解的一种方式,我成功的包装了普通算法的COM版,但是尝试 了很长时间不能成功实现并行运算 的版本,也就放弃在这里展示了,如果你知道 如何在WRL中实现并行计算并返回 IAsyncOperation,请不吝赐教。 

小结:基于C++的实现在适用性、稳定性和执行效率上无可挑剔,如果对于所有 细节(包括***次启动)的效率考虑,C++是优先 的;如果考虑到C++的复杂度, 如果项目对性能要求可以适当放松但对进度要求很高的时候,选择CLR会比较容易 控制的;如果原来已有的Web项目 向WinRT迁移,那么前段展示则可以考虑使用 WinJS+HTML来实现,后台算法根据需要选择C++或者CLR。

第三部分,如果所有的算法全部运行在 JavaScript中,那么其性能如何呢?这里我先买个关子,留待你自己去探究和发 掘。

总结,WinRT在编程语言的选择性上有着非常好的 灵活性,在做选择的时候需要充分考虑自己的要求,比如性能、比如工期、比如经 验等 等。对于全新项目,在有经验的情况下,追求***性能的首先首当其冲是 C++,如果考虑到经验和掌控,可以选择使用C++做底层,选择相对容易上手 的 C#/VB或者HTML+JS做界面的方法;如果项目工期要求很紧,或者从老系统迁移,那 么这时候更多的考虑是使用已有资源,直到性能瓶颈的时 候才采取措 施——以C++重写性能瓶颈来解决,当然,如果没有C++经验,也可以考 虑使用C#/VB来 实现WRC以包装核心逻辑,从而提升运行效率。

附以上测试源代码和测试工程,点击这里下载。

当前文章:WinRT开发的功能和效率
转载来源:http://www.shufengxianlan.com/qtweb/news19/94769.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联