分布式科学计算与Docker

作者:Ghostcloud-谢斌

在科学计算领域, 早些年的程序语言基本都是C/C++或者FORTRAN的天下, 是因为科学计算本身非常耗时, 选择一门运行速度比较快的语言能大大的节约对数据的计算时间. 但是在保证速度的之后, 语言的通用性和易用性又成了一大问题. C语言虽然语法简单明了, 执行速度快. 但是它的开发难度却是所有语言中最大的. 面向对象的变成方法需要借助比如structure这一类的特性来实现. 并且也没有太多的第三方库可供使用. 所以在开发复杂系统的时候, 需要很强的规划能力. 而C++或者其他语言, 又因为学习成本高, 往往只是少部分专业程序员能用到滚瓜烂熟. 一个算法实现不好便会大大的降低运行速度. 我相信很多做过程序员的朋友都有这样的体会, 即便是用C来写一个算法, 如果实现的不够精妙, 往往运行速度还不如ruby, perl这些脚本语言的第三方库. 因为这些第三方库虽然有先天的劣势, 但是这些相关的函数确是从算法上精心锤炼过的. 设计不好的算法+先天的编译优势vs精炼的算法+解释型语言, 谁的速度快其实更多的, 就是看运气了.

所以是否有一种方法, 有C的快速,Ruby的动态,Java的通用,R般在统计分析上得心应手,Perl的处理字符串处理,Matlab的线性代数运算能力. 易学又大碗呢.

Python作为一门通用的面向对象的程序设计语言, 已经越来越多的应用在各个领域. 包括金融业, 制造业以及数据信息产业. 基于python的程序库也是越来越多并且功能越来越强. Python的通用性和易上手性以及不用讨论了, 现在很多非科班程序员出身的哥们儿以及能在基于python的各种库中实现自己想要的功能. 做金融数据分析的, 做图像识别的, 做自动化的. 几乎每一个专业都能在python上找到自己相关的专用库. 前几天还听说python会纳入小学课程. 也不知道是段子还是真的. 但是从目前的情况来看. Python确实已经融入到了生产环节的方方面面.

目前科学计算比较流行的方法是用python作为胶水, 再把c, c++这些高速语言实现的计算库进行实际的数学计算. 比如著名的Tensorflow, pandas, numpy等等这些使用宽泛的库. 程序的逻辑又python控制, 数据在各个库里面计算, 输入和输出. 这样的话, 程序本身的性能和易用性得到了最大化的提升.

科学计算的速度除了之前说的和语言相关, 还包括另外2个关键要素, 第一个是分布式, 第二个是系统资源的限制(包括CPU, Memory和Storage).

语言和运行平台的问题, 我们可以通过python+计算库来实现, 但是分布式和系统资源呢.

首先, 如果我们要实现科学计算的分布式, 除了在程序里面自己实现之外, 还有很多相关的开源框架, 比如hadoop + hive这类的大数据现成框架. 但是这一类的系统偏大偏重, 且升级更新不够自动化和轻量.

其实有一种更为轻量级的方式, Docker+K8s实现分布式计算和资源自动划分.

原理很简单, 我们在实现算法的时候, 并不要求实现分布式的架构, 只需要能读取数据, 计算分析数据, 然后输出数据到文件即可. 在实现算法的程序之后, 我们将程序和依赖环境封装成docker镜像. 并且放到docker的镜像仓库里面. 使用k8s对镜像进行自动化的调度, 我们可以设置规则说, 每一个物理主机只能运行一个容器或者运行多个容器. 然后把每一个容器的输出结果定向到共享存储. 只需要简单的几步, 基本上一个有自动调度功能, 资源划分功能, 高可用功能和运行状态监控功能的一个分布式计算系统就已经搭好了.

之后, 我们只需要加入负责计算的节点, k8s会自动根据CPU/Memory的阈值自动做负载均衡. 举个例子来说, 我们甚至不用指定说哪些容器运行在哪些主机上, 只需要启动pod并且指定并发数量, k8s就会自动将这个计算程序的镜像分布到每一个可用的计算节点上. 并且自动负载均衡. 当计算完成之后, K8s的检查到pod没有使用的情况. 会自动删除相关的pod, 释放资源给其他计算服务使用.

K8s自带健康检查功能, 所以我们可以使用这个功能来实现对容器运行状态的监控. 一旦发现job出了问题, 我们可以选择重启, 终止, 或者路由到其他计算节点上面.

并且根据Docker轻量级的特性, 我们可以用devops实现其计算镜像的快速部署. 只需要在编译好代码后更新镜像仓库里面对应的镜像. K8s会自动升级所有有关的pod, 让运行的程序始终是最新的.

Docker和科学计算的结合, 其主要优势在于快速部署和计算资源的统一管理. 相对比较轻. 且对环境要求不高. 老旧机器, 新机器, 都可以加入到计算集群. 以实现资源的最大化利用.