今天,当我看到一个数据集,其中最小的文件是48000个字段乘1600行(几个人的单倍型,22号染色体)时,我今天刚刚迈出了我的第一个宝贝步骤进入真正的科学计算.这被认为是微不足道的.
我写Python,所以我花了最后几个小时阅读有关HDF5,Numpy和PyTable的内容,但我仍然觉得我并不是真正想要一个TB级数据集对于我作为程序员的实际意义.
例如,有人指出,对于较大的数据集,不可能将整个内容读入内存,不是因为机器内存不足,而是因为架构的地址空间不足!它让我大吃一惊.
还有什么其他的假设我一直在教室里依赖这个大的投入?我需要做些什么才能开始做或以不同的方式思考?(这不一定是Python特定的.)
我目前正在石油行业的一个小角落从事高性能计算,并定期处理您所关注的数量级的数据集.以下是需要考虑的一些要点:
数据库在这个领域没有很大的吸引力.几乎所有数据都保存在文件中,其中一些文件基于70年代设计的磁带文件格式.我认为不使用数据库的部分原因是历史性的; 10年前,甚至5年前,我认为甲骨文和它的亲属不能完成管理O(TB)单个数据集的任务,更不用说1000个这样的数据集的数据库了.
另一个原因是有效数据库分析和设计的规范化规则与科学数据集的性质之间存在概念上的不匹配.
我认为(虽然我不确定)今天表现原因的说服力要低得多.现在,大多数可用的主要数据库都可以应对空间数据集,而这些空间数据集通常与其他科学数据集的概念更接近,因此概念不匹配的原因可能也不那么迫切.我已经看到越来越多地使用数据库来存储元数据,然后对包含传感器数据的文件进行某种引用.
然而,我仍然在看,实际上我正在看,HDF5.它对我来说有几个吸引力(a)它只是另一种文件格式,所以我不需要安装DBMS并且必须解决其复杂性,并且(b)使用合适的硬件我可以并行读/写HDF5文件.(是的,我知道我也可以并行读写数据库).
这让我想到了第二点:处理非常大的数据集时,你真的需要考虑使用并行计算.我主要在Fortran工作,它的一个优点是它的数组语法很适合很多科学计算; 另一个是对可用的并行化的良好支持.我相信Python也有各种并行化支持,所以它对你来说可能不是一个糟糕的选择.
当然,您可以在顺序系统上添加并行性,但最好是开始设计并行性.举一个例子:问题的最佳顺序算法通常不是并行化的最佳候选者.您可能最好使用不同的算法,在多个处理器上可以更好地扩展.这导致整个下一点.
我认为你可能不得不放弃将你拥有的任何附件(如果有的话)放弃到许多聪明的算法和数据结构,这些算法和数据结构在你的所有数据驻留在内存中时都能很好地工作.经常尝试使它们适应无法将数据同时存入内存的情况,比蛮力更难(并且性能更低)并且将整个文件视为一个大型阵列.
性能开始严重影响,无论是程序的执行性能还是开发人员的性能.并不是1TB数据集需要的代码是1GB数据集的10倍,因此您需要更快地工作,这就是您需要实现的一些想法将会非常复杂,并且可能必须由域专家编写,即你正在与之合作的科学家.这里的域专家用Matlab编写.
但这种情况持续太久,我最好还是回去工作
简而言之,IMO的主要区别:
您应该事先知道您可能遇到的瓶颈(I/O或CPU),并专注于解决此问题的最佳算法和基础架构.I/O经常是瓶颈.
算法的选择和微调通常支配任何其他选择.
即使对算法和访问模式进行适度更改也会影响性能数量级.你将进行微观优化."最佳"解决方案将取决于系统.
与您的同事和其他科学家交流,从他们使用这些数据集的经验中获益.在教科书中找不到很多技巧.
预先计算和存储可以非常成功.
带宽和I/O.
最初,带宽和I/O通常是瓶颈.为了给你一个观点:在SATA 3的理论极限下,读取1 TB需要大约30分钟.如果您需要随机访问,多次读取或写入,您希望在大多数情况下在内存中执行此操作或者需要更快的速度(例如,使用InfiniBand的iSCSI).理想情况下,您的系统应能够进行并行I/O,以尽可能接近您使用的任何接口的理论极限.例如,只需在不同进程中并行访问不同文件,或在MPI-2 I/O之上访问HDF5很常见.理想情况下,您还可以并行执行计算和I/O,以便其中一个"免费".
集群
根据您的情况,I/O或CPU可能不是瓶颈.无论它是哪一个,如果您可以有效地分配您的任务(例如MapReduce),群集可以实现巨大的性能提升.这可能需要与典型的教科书示例完全不同的算法.在这里花费开发时间通常是花费的最佳时间.
算法
在算法之间进行选择时,算法的大O非常重要,但具有相似大O的算法在性能上可能会有很大差异,具体取决于位置.算法本地越少(即更多的缓存未命中和主内存丢失),性能越差 - 访问存储通常比主存储器慢一个数量级.改进的经典例子是矩阵乘法或循环交换的平铺.
计算机,语言,专业工具
如果您的瓶颈是I/O,这意味着大数据集的算法可以受益于更多的主存储器(例如64位)或具有更少内存消耗的编程语言/数据结构(例如,在Python中__slots__
可能有用),因为更多的内存可能意味着每个CPU时间的I/O更少.顺便说一句,具有主存储器TB的系统并非闻所未闻(例如HP Superdomes).
同样,如果你的瓶颈是CPU,那么允许你使用架构的特殊功能(例如像SSE这样的SIMD)的更快的机器,语言和编译器可能会将性能提高一个数量级.
您查找和访问数据以及存储元信息的方式对于提高性能非常重要.您将经常使用平面文件或特定于域的非标准软件包来存储数据(例如,不是直接关系数据库),以便您更有效地访问数据.例如,kdb +是用于大型时间序列的专用数据库,ROOT使用TTree
对象有效地访问数据.你提到的pyTables就是另一个例子.