个人项目总结 (By Jun Guo)
为期两周的个人项目就这样过去了。虽然说还有很多不足的地方,但自己还是比较满意吧,毕竟是认真做了的。
项目挺简单的,就是做一个词频统计程序,用来统计文章里各个单词出现的次数。可以说,这已经简单到不能称为“项目”了。不过,写这个程序前前后后还是遇到挺多问题——毕竟,要将效率优化到极致实在是很麻烦的事情。
一开始秋丰老师给出超级指标——要让程序能处理10G数据。当时一看到这个指标我就各种囧,因为万一10G数据里所有单词都不同(即每个单词的词频都为1),这堆单词连直接存放在内存中都做不到。为了解决这个问题,程序就不得不在处理了部分数据后就将该部分的词频统计结果保存到文件上,最后再将这些文件合并输出结果。将数据分开来处理倒还不是很困难,真正难的部分在于合并。所谓的合并指的是,比如A文件里记录单词hello出现了1次,B文件里记录单词hello出现了2次,那我们要将结果合并为hello出现了3次。为了在较低的复杂度下完成合并,程序就需要先将各个文件整理为有序,最后再采用多路合并将这些文件综合在一起得到结果——这本质上就是外部排序。众所周知,外部排序的效率与磁盘块大小、磁盘缓存大小、文件系统缓存大小等息息相关,为了达到最高效率,代码必须调用Win 32 API来完成有关的检测。
于是,在秋丰老师超级指标的压迫下,一份极其复杂的外部排序代码诞生了。然而,在做测试时我就发现,虽然程序对付大数据确实非常高效,但对付小数据实在力不从心——对于一份只有几M的文件,采用简单的哈希或红黑树,在内存中完成对所有单词的统计显然会比优化到极致的外部排序还要快得多。一想到要针对不同大小的文件写不同算法,还要通过大量测试来选定一个最佳的阈值(超过阈值就切换算法),我的心顿时就发毛了……于是,果断联系了秋丰老师。在打扰了秋丰老师N次之后,终于得到一个肯定的答复——测试数据中不同单词数不会超过100万个。这总算让我舒了一口气,终于不用去寻找最优阈值了;但这也同时宣告那堆外部排序的代码可以进垃圾桶了……
就这样,重建一个工程,开始用哈希表来解决词频统计的问题。既然提到哈希表,那首先就要选定一个优秀的哈希函数。字符串哈希印象中效果比较好的有ELF Hash、BKDF Hash这几个。我生成了些数据,测试一下各个哈希函数的碰撞率,同时记录下各个哈希函数进行哈希运算的时间开销,最后发现BKDF Hash无论是碰撞率还是哈希开销都远远优于其他函数,于是BKDF Hash就成必然选择了。
之后要将哈希函数运用到容器上。C++0x下的STL多了个unorder_map,是一个基于哈希的无序容器,理论上能提供 比红黑树的map更优的查找与插入性能。不过,根据我以前写代码的经历,STL的各种容器向来都是低效的代表,这个unorder_map估计也是如此。经过测试,果然很坑爹慢……算了,反正自己写个哈希表也不麻烦,于是就动手写了。为了容易解决冲突,用了开放式链表法;为了减少new操作的开销,又将开放式链表法里的链表换成数组链表。
除此以外,为了减少那缓慢的string所带来的开销,还重写了string类……
除了还有一些微不足道的最小堆优化等等,程序基本上也没什么好说的了。事实上,一开始在采用哈希表之前,我也考虑过用字典树来解决。但后来一想,字典树是O(length)插入,哈希表也是O(length)插入,而且字典树的插入常数与基于BKDF Hash的哈希表基本一样(对于每个字符,字典树是一次判断一次赋值外加一次new,BKDF是一次乘法一次加法外加一次赋值;字典树的new操作不一定发生,但一旦发生开销极大——虽然我也试过用内存池或者预先分配来改进之,但效果不明显,有时反而更慢),再加上字典树有爆内存的风险,因此最后并没有采用(代码留着,但没有调用)。
最后经过秋丰老师的测试,在普通机械硬盘上,340M的数据大概4s多就跑完,平均1s能处理80M数据,可以说瓶颈已经不在程序而是在硬盘上了。这还是让我较为满意的。
PS 1.
按秋丰老师要求,我在完成这个个人项目时也统计了下代码行数和开发时间。如今对比一下完成项目前的时间预估,发现结果很搞笑。一开始我预计大概要写1500行代码,总的开发时间则预估为50小时;但最后总共才写了627行代码,总的开发时间却花了29小时。虽然真实的开发时间比预计的要少,但从单位时间所编写的代码量来看,原有预计还是过高估计了产出效率了……不过,能提前完成任务也是件不错的事情。
PS 2.
有人问我为什么没有用C#。确实啊,我是个重度C#控,为何在上文一直没提到C#呢?呃,其实原因是——我在做个人项目前升级了.Net Framework,结果不小心给安装失败了,不但新装的.Net Framework 4.5用不了,连以前的.Net Framework 2.0/3.5/4.0一律都用不了。而我当时又忙着看论文,所以没有时间去检查安装失败的原因,于是只能蛋疼地用C++了……
转载于:https://www.cnblogs.com/smart-code/archive/2012/09/07/2674604.html
个人项目总结 (By Jun Guo)相关推荐
- mSystems和Microbiology Spectrum杂志“肠道微生态专题”论文征稿
美国微生物学会(American Society for Microbiology,ASM)是生命科学领域中全球最大且历史最悠久的会员组织,创办了多个高影响力学术期刊.目前会员超过 30000 人,旗 ...
- Daily Scrum M2 11-14
今天算是有很多进展的一天. 首先是数据方面的一个bug被发现并修复了,现在输入一个关键词之后就马上能获得相当多的结果. 数据方面的充足的一个好处是大家在测试的时候就不用自己伪造数据了,一开始获得的数据 ...
- CVPR 2015 papers
CVPR 2015 CVPR 2015的文章可以下载了,如果链接无法下载,可以在Google上通过搜索paper名字下载(友情提示:可以使用filetype:pdf命令). Going Deeper ...
- 使用Nant构建入门
前言: NAnt是一项开源的项目,利用NAnt,你可以方便快捷地对自己.NET项目或解决方案进行自动构建.与VS中可视化化极强的项目和解决方案管理相比,NAnt只能命令行的方式操作,但是这并不影响Na ...
- 【今日CV 计算机视觉论文速览 第110期】Thu, 2 May 2019
今日CS.CV 计算机视觉论文速览 Thu, 2 May 2019 Totally 22 papers ?上期速览✈更多精彩请移步主页 Interesting: ?3DFaceGAN, 基于对抗网络的 ...
- 【今日CV 视觉论文速览】Fri, 15 Feb 2019
今日CS.CV计算机视觉论文速览 Fri, 15 Feb 2019 Totally 49 papers Daily Computer Vision Papers [1] Title: Deep Gen ...
- 计算机视觉论文-2021-06-16
本专栏是计算机视觉方向论文收集积累,时间:2021年6月16日,来源:paper digest 欢迎关注原创公众号 [计算机视觉联盟],回复 [西瓜书手推笔记] 可获取我的机器学习纯手推笔记! 直达笔 ...
- Daily Scrum M2 11-5
本周开始,我们的ASE课程设计中的Milestone2又要开始了,依然是10天的Daily Scrum.当然我们做的还是和M1一样的东西,只是有更多的改进. 今天是Scrum的第一天,基本上大家还都是 ...
- CVPR 2018 paper list(论文列表)
原文链接:http://cvpr2018.thecvf.com/program/main_conference 52 Embodied Question Answering Abhishek Das ...
最新文章
- 使用容器和数据库克隆进行数据库迁移
- ElasticSearch(一)ElasticSearch的应用场景及为什么要选择ElasticSearch?
- Network 第七篇 - 网络地址转化
- C++ STL : 模拟实现STL中的关联式容器unordered_map/unordered_set
- Python第二十天 shutil 模块 zipfile tarfile 模块
- 一个月工资6500,一年存了五万左右,算节省吗?
- strust2 和 hibernate的整合------登录的实现
- 深度揭秘 如何将PDF转换成Word的技巧
- WSO2流处理器相关学习(1)快速入门指南【转】
- 智能POS机项目原理分析
- Kafka的入门级API应用
- Linux内核基础--事件通知链(notifier chain)good【转】
- 计算机的中央处理器CPU包括什么,中央处理器cpu由哪些组成 中央处理器的作用是什么...
- TC27x寄存器学习
- 春招秋招笔试面试时间(2020年)
- 如何用课件制作工具演示长方形展开动画
- 让SpringBoot不需要Controller、Service、DAO、Mapper,卧槽!这款工具
- Matlab 实现 数值计算方法 二分法
- 好网线与坏网线的区别,教你几招鉴别技巧
- 非线性规划问题求解(举例)