问题原因:

最近由于工作实际需求,需要对某个计算单元的计算方法进行重构。原因是由于这个计算单元的计算耗时较长,单个计算耗时大约在1s-2s之间,而新的需求下,要求在20s内对大约1500个计算单元计算完毕。如果不对原有计算单元的计算方法进行优化及效率提升,那么以8核CPU(超线程16线程)来说,在单个计算1s的理想条件,服务器16线程完成任务的理论上限也需要90s+,何况多线程还并不是简单的效率叠加,实际测试情况下,耗时往往在150s以上。因此,对原有计算单元的计算优化是必须的。

问题分析:

通过对原有计算单元的实现过程查看,计算任务存在大量的数据库读取及大量的比对、计算等操作,涉及的数据表的数量级从数百到百万不等,这些数据表有一个相同的特点就是相对固定,并不是实时业务数据。通过对原有计算过程的分析,主要的耗时就在各种条件比对及比对后进行的数据库IO操作。

因此,要提高效率,首先想到的就是如何减少数据库的IO次数,但实际的计算任务是一个很严格的时序型逻辑,即每一步的处理输入是上一步的数据处理结果。因此要在单个计算任务中进行并行计算的改造很难,并且,由于单次数据库IO的时间开销也不大,因此进行异步化改造也不合适,反而会增加代码的复杂度。

所以最终还是把思路集中在如何对计算任务本身进行优化。

解决方式:

经过对计算任务的分析,在这种场景上下文中,决定以哈希定位作为解决方式(这是一种可能的解决方式,但并不一定是最优的)。

通过前文对计算任务的分析,所涉及的数据都是相对固定的,因此首先考虑将所有数据加载到内存(由于数据量并不是非常的大,服务器内存还能承受,可根据实际需求加载到mem或redis中)。如果仅仅是将数据加载到内存,再用linq2object替代原有的数据库IO,提升并不大,因为计算逻辑中最耗时的操作是对数据的范围查询,即数据并没有精确匹配,而是需要找到目标值对应数据的上下限,并进行线性插值运算。

如果能将范围数据查询的工作以更快速更精确的方式来实现,就省下了计算逻辑中最大的时间开销。因此考虑才用呢哈希定位的方式进行。

具体改造过程不再赘述,工作难点主要在于哈希KEY的构造,以及如何通过哈希寻址实现数据库查询中的‘> and <’条件操作。具体来说,通过将范围值扩大量纲变为整数,并以最小步长提前做线性插值,即可形成满足要求的哈希KEY,同时,通过对需要定位的值,对步长进行除法取整,即可得到目标值的下限值,再对下限值加上步长,即可得到上限值,从而通过一次哈希寻址,得到之前需要在数据库进行‘> and <’操作的结果。

解决结果:

通过以上改造,在该计算任务场景中,对1000+计算单元进行计算的时间开销已降低到1-4秒(由于是WCF服务调用,因此需要视网络通信等状况而定),完全可以满足需求。

通过对这次计算任务的重构,可以看出,对计算密集型/IO密集型任务,异步化及并行计算等优化方法很难进行,并且提高会非常有限(计算密集型任务),因此,通过对原子任务本身的优化来达到最终目标也是一个重要的思路。

计算&IO密集型任务的 优化的更多相关文章

  1. 浅谈Java两种并发类型——计算密集型与IO密集型

    转载:https://blog.csdn.net/u013070853/article/details/49304099 核心是可以分别独立运行程序指令的计算单元.线程是操作系统能够进行运算调度的最小 ...

  2. Python IO密集型任务、计算密集型任务,以及多线程、多进程

    对于IO密集型任务: 直接执行用时:10.0333秒 多线程执行用时:4.0156秒 多进程执行用时:5.0182秒 说明多线程适合IO密集型任务. 对于计算密集型任务 直接执行用时:10.0273秒 ...

  3. IO密集型 计算密集型

    参考:https://www.cnblogs.com/zhangyux/p/6195860.html 参考:廖雪峰 协程 gevent IO密集型任务指的是磁盘IO或者网络IO占主要的任务,计算量很小 ...

  4. [Python]IO密集型任务 VS 计算密集型任务

    所谓IO密集型任务,是指磁盘IO.网络IO占主要的任务,计算量很小.比如请求网页.读写文件等.当然我们在Python中可以利用sleep达到IO密集型任务的目的. 所谓计算密集型任务,是指CPU计算占 ...

  5. cpu,io密集型计算概念

    I/O密集型 (CPU-bound) I/O bound 指的是系统的CPU效能相对硬盘/内存的效能要好很多,此时,系统运作,大部分的状况是 CPU 在等 I/O (硬盘/内存) 的读/写,此时 CP ...

  6. CPU计算密集型和IO密集型

    CPU计算密集型和IO密集型 第一种任务的类型是计算密集型任务,其特点是要进行大量的计算,消耗CPU资源,比如计算圆周率.对视频进行高清解码等等,全靠CPU的运算能力.这种计算密集型任务虽然也可以用多 ...

  7. 题外话:计算密集型 vs IO密集型

    我们把任务分为计算密集型和IO密集型,erlang作为IO密集型的语言,适合网关等相关的场景,而对计算达到某一量级后,可能处理效率下降的很明显. erlang不适合数值计算.erlang是解释型的,虽 ...

  8. 计算密集型和 io 密集型项目的使用场景分析和代码演示

    from threading import Thread from multiprocessing import Process import time 计算密集型 def work1(): res= ...

  9. 并发编程~~~多线程~~~计算密集型 / IO密集型的效率, 多线程实现socket通信

    一 验证计算密集型 / IO密集型的效率 IO密集型: IO密集型: 单个进程的多线程的并发效率高. 计算密集型: 计算密集型: 多进程的并发并行效率高. 二 多线程实现socket通信 服务器端: ...

随机推荐

  1. 网页动物园2.0发布,经过几个月的努力,采用JAVA编写!

    网页动物园2.0发布,经过几个月的努力,采用JAVA编写! 网页动物园2.0 正式发布!游戏发布 游戏名称: 网页动物园插件 游戏来源: 原创插件 适用版本: Discuz! X1.5 - X3.5 ...

  2. 代码静态解析PMD

    在正式进入测试之前,进行一定的静态代码分析及code review对代码质量及系统提高是有帮助的,以上为数据证明 Pmd 它是一个基于静态规则集的Java源码分析器,它可以识别出潜在的如下问题:– 可 ...

  3. Vs 2015 调试ASP.NET Core修改监听端口

    如何改变监听IP地址和端口?在这里找到了答案:https://github.com/aspnet/KestrelHttpSer... 把Program.cs加一行UseUrls代码如下: using ...

  4. html post和get的区别

    一直以来,都对这两个概念有一个感性的认识,今天总结一下: 1.Get是用来从服务器上获得数据,而Post是用来向服务器上传递数据. 2.Get将表单中数据的按照variable=value的形式,添加 ...

  5. [转]nginx+fastcgi+c/c++搭建高性能Web框架

    FROM : http://blog.csdn.net/marising/article/details/3932938 1.Nginx 1.1.安装 Nginx 的中文维基 http://wiki. ...

  6. vs 2005 thread 无法调试

    两种办法:1.打开项目属性,在“Debug”一项里,把“Enable the Visual Studio hosting process”前的钩去掉.这个方法不是好办法.2.打开计算机管理,在服务里将 ...

  7. Cannot resolve external dependency com.android.support:multidex:1.0.0

    multiDexEnabled true 去掉这一行,就OK了,是没有多dex支持么,但是又提供了这个

  8. mac/linux中vim永久显示行号、开启语法高亮

    步骤1: cp /usr/share/vim/vimrc ~/.vimrc 先复制一份vim配置模板到个人目录下 注:redhat 改成 cp /etc/vimrc ~/.vimrc 步骤2: vi ...

  9. ehcache2.8.3入门示例:hello world

    一.pom.xml 依赖项 <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehc ...

  10. ubuntu15.10 或者 16.04 或者 ElementryOS 下使用 Dotnet Core

    这里我们不讲安装,缺少libicu52自行安装. 安装完成后使用dotnet restore或者build都会失败,一是报编译的dll不适合当前系统,二是编译到ubuntu16.04文件夹下会产生一些 ...