程序员应知 -- 如何分析海量数据

程序员应知 -- 如何分析海量数据

http://www.cnblogs.com/MicroTeam/archive/2010/12/03/1895071.html

在这个云计算热炒的时代,如果你没有处理过海量数据的话,你将不再是个合格的Coder。现在赶紧补补吧~

前一阵子分析了一个将近1TB的数据群(gz文件,压缩率10%)。因为第一次分析如此巨大的数据,没有经验,所以浪费了许多时间。下面是我整理的一些经验,方便后者。

欢迎各种补充,我会不断更新这篇文章;觉得有用的话,速度分享链接;有不同意见的话,请果断拍砖;


下载数据

Q:怎么自动下载多个文件?

这是我遇到的第一个问题。当数据量很大时,一般都会分成很多个文件存放。这时下载文件比较麻烦。

A:用Wget命令。Windows下花费一点时间去下载安装。但之于手动下载,能省不少时间。

我提供两种方式方式下载文件,

a)用Wget的递归下载选项 “-r”。一般命令如下

wget –r http://<下载数据的根目录>/  -o <下载记录文件名>  -np

因为递归下载没法控制进度,所以建议不一要次递归下载太多的文件

b)用Bat+Wget,多次执行Wget。一般命令如下

wget –r http://<下载数据的根目录分支1>/  -o <下载记录文件名>  -np

wget –r http://<下载数据的根目录分支2>/  -o <下载记录文件名>  -np

wget –r http://<下载数据的根目录分支3>/  -o <下载记录文件名>  -np

…… ……

wget –r http://<下载数据的根目录分支N>/  -o <下载记录文件名>  -np

用Bat可以降低出错带来的影响。

另外,Wget可以通过 –A 选项来指定希望下载的文件的后辍,通过 –P 选项来指定下载文件存放路径。更多命令,参见wget -h

Q:这速度。。。什么时候才能下完?

网速永远是个瓶颈

A:如果下载服务很远的话,你应该考虑代理。wget设置代理的方式如下

set http_proxy=http://<代理服务器>

不要忘了多开几个进程,20个试试?

打开文件

Q:怎么打开文本文件

这不是弱智问题。你用记事本打开一个1000MB的文件试试

A:LTF viewer

Large Text File viewer, 打开速度会让你惊奇

Q:怎么打开二进制文件

A:Hex Editor Neo

你可以通过下面方式来选择进制:

右击数据区 => Display As => Hex|Decimal|Octal|Binary|Float|Double

你可以通过下面方式来选择按多少字节显示:

右击数据区 => Group By => Bytes|Words|Double|Quad

编程语言

当数据量很大时,选择语言要慎重了。因为不同语言有不同的特点,你要在编程时间和运行时间之间权衡。

模型测试

开始时,一般挑几个小的数据进行测试,获取第一份分析结果。这时当然希望能快速编程实现。脚本语言是一个很好的选择,比如Python。

大量处理

开始遍历处理所有数据时,用脚本语言来处理就不太合适了。因为脚本语言的运行时间不能让人接受。另外,还有内存使用,文件读写这些你都没法控制。不幸的是,很少语言会为你处理海量文件做优化。

这时,C/C++是最好的选择。

结果展示

漫长的等待终于过去了,眼看就要出结果了。如果你还执着于陪伴你度过漫长等待的C/C++的话,你迟早会沮丧的。

我尝试了很多方式之后,得出的结论是,让Matlab来接手C/C++。Matlab能轻而易举地展示大量数据。更重要的是Matlab支持读取二进制文件。

filename = ‘out.bin‘;        % binary file
fid = fopen( filename );
data = fread( fid, itemsNumber, ‘*uint32‘);
fclose(fid);

算法

一次性读文件

我已经测试过好几次了,一次性读取文件比一行一行读文件至少快五倍

记住O(N)

这时你要好好考虑算法的复杂度了。任何O(N2)的算法都不可取。

必要的时候可以通过空间来换时间。通常哈希表能节省不少时间。

并行处理

温习一下并行算法。这比等待单线程程序好很多。

可以考虑在GPU上跑程序。当然,内存和文件读取时间更可能是瓶颈。

内存、CPU、磁盘读取速度,谁是瓶颈,任务管理器知道。

优化核心代码

通常80%的时间在运行20%的代码。所以有空的话优化下经常经常执行的代码。

分布式保存

把分析结果存在一个文件中是一个很糟糕的决定。这会为后面处理带来很多麻烦。比如并行处理,文件过大等。

二进制方式保存中间数据

二进制方式存放通常能省一半的磁盘空间。这同时意味着减少一半的写硬盘时间和读硬盘时间。当然,还有文本转换时间。

还有个重要细节要注意:在Windows中,读写文件的方式要改成”rb”和”wb”。要不然莫名的Bug迟早要发生,但不一定能找到。

运行

Debug Vs Release

别忘了,最终运行时把编译方式换成Release。但是刚改完程序的话,建议先用Debug模式试跑一下。这样能定位运行时异常。

批处理

批处理是降低运行出错风险的很好的方式。因为你不确定程序能正常结束。所以一段一段执行程序是一个很好的选择。如果某个地方出问题的话就不用重新运行前面的程序了。

断言

当数据量很大时,很难保证输入是合法的。另一种情况是,数据是合法的,但我们欠考虑了。这时断言就显得很重要了。断言回增加运行时间,但总比花大量时间得到一个错误结果好。

记录运行结果到文件

前面提到,数据量很大时,很难保证程序正常结束。一般,很少人会在显示器旁坐等输出结果。把运行情况定时记录到文件是非常必要的。

另外,不要忘了fclose();

附:64位编程问题

数据量很大时,内存通常是不够用的。有一个常识必须知道:32位程序的最大寻址空间是2GB。如果你要分配接近或者超过2G内存的话,试试64位程序吧。当然有两条件:64位的CPU,64位的操作系统。

下面是编写64位程序的一些经验

编译环境

如果是解释型语言,比如Python,则需要下载一个64位的Python解释器

如果是编译型语言,比如C/C++,则需要选择恰当的编译平台。

比如VS2008中,项目属性 => Configuration Manager => Platform => New => X64

内存

分配大数组,应该用malloc,而不是直接定义数组。

sizeof( int )  != sizeof( size_t )

64位程序中,数组下标应该换成size_t,常数也需要强制转换,比如 4GB = 4*(size_t)1000000000000

文件

fwrite一次性写入一个大于4GB的数组似乎有些问题。

分多次写入文件试试。

时间: 2024-10-18 10:38:33

程序员应知 -- 如何分析海量数据的相关文章

新入行程序员应知的十个秘密

新入行程序员应知的十个秘密 初出茅庐的你带着仍残留墨香的毕业证书踏上工作岗位,马上就被书上没写的规则和各种繁杂的日常事务来了个下马威.这样的故事实在是司空见惯,编程工作也不例外. 没有几个学生能 100% 为自己的第一份真正的工作做好准备.如果你不想成为其中之一,请学学以下这 10 项无需手把手指导就能学会的基本技能: 1.版本控制系统(VCS) VCS 也许是计算机课程最大的疏漏.这些课程光记得教如何写代码,但却往往忘记教学生如何去管理代码.每一个程序员都应该懂得利用 Git 或 Subver

嵌入式程序员应知道的0x10个C语言Tips

[1].[代码] [C/C++]代码 跳至 [1] ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77

嵌入式程序员应知道的0x10个基本问题

来源:网络 1 . 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL我在这想看到几件事情:1) #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)2)懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的.3) 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉

【转】嵌入式程序员应该知道的16个问题

全面解析<嵌入式程序员应该知道的16个问题> ----Sailor_forever分析整理,[email protected] http://blog.csdn.net/sailor_8318/archive/2008/03/25/2215041.aspx 1.预处理器(Preprocessor) 2.如何定义宏 3.预处理器标识#error的目的是什么? 4.死循环(Infinite loops) 5.数据声明(Data declarations) 6.关键字static的作用是什么? 7.

程序员必知的10大基础实用算法

    算法一:快速排序算法 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2) 次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的 架构上很有效率地被实现出来. 快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists). 算法步骤: 1 从数列中挑出一个元

php程序员应具有的7种能力

php程序员应具有什么样的能力,才能更好的完成工作,才会有更好的发展方向呢?在中国我想您不会写一辈子代码的,那样不可能,过了黄金期,您又怎么办呢?看了本文后,希望对您有所帮助. 一,php能力 1,了解阶段,您能写一些代码,因为那是在手册和google的帮助下,您才完成的.变量乱定义,N多函数不知道,做起事来很慢,想到什么写什么,代码写的比较乱,后期维护很麻烦. 2,熟悉阶段,经常查函数,手册估计也看过一,二遍了,常用的函数基本上您都了解了.后 期维护给您带来了不少痛苦,您开始发现自己的代码有很

程序员应具备的7大技能

1.  对技术的热忱 热情是一种无形的东西,当你所列清单上的所有事情都做不好的时候,它常常能帮你熬过这段时间.对IT的强烈热爱,也会让你的其他大部分特点都遥遥领 先,这是纯粹的智商和商业头脑所无法比拟的.当你在IT行业工作了多年之后,热情也会帮你在早上起床之后期待今天的工作.没有热情,IT领域将会成为一个 空有外壳没有灵魂的地方. 2.  懂得数据分析 数据是IT企业和它所服务的企业的命脉.对公司数据有深入的了解,可以对软件应用程序与数据的衔接提供重要的见解.此外,从商业的角度看,如果你对 一个

迈向高阶:优秀Android程序员必知必会的网络基础

1.前言 网络通信一直是Android项目里比较重要的一个模块,Android开源项目上出现过很多优秀的网络框架,从一开始只是一些对HttpClient和HttpUrlConnection简易封装使用的工具类,到后来Google开源的比较完善丰富的Volley,再到如今比较流行的Okhttp.Retrofit. 要想理解他们之间存在的异同(或者具体点说,要想更深入地掌握Android开发中的网络通信技术),必须对网络基础知识.Android网络框架的基本原理等做到心中有数.信手拈来,关键时刻才能

(转) Java程序员应该知道的10个调试技巧

原地址:http://www.csdn.net/article/2012-09-03/2809495-java-debugging-tips-with-eclipse 调试可以帮助识别和解决应用程序缺陷,在本文中,作者将使用大家常用的的开发工具Eclipse来调试Java应用程序.但这里介绍的调试方法基本都是通用的,也适用于NetBeans IDE,我们会把重点放在运行时上面. 在开始之前,推荐大家去看看Eclipse shortcuts这篇文章,它将会给你带来很多方便.在本文中使用的是Ecli