当Python和R不能依赖于C/C++所支持的功能或库时,它们就会变得很慢。它们不仅对于某些算法开发是低效的,而且对于诸如FASTQ解析这样的常见任务也是低效的。使用这些语言限制了生物学家的研究。有时,您可能有一个绝妙的想法,但仅仅因为使用的语言不能快速实现。这可能会令人沮丧。我一直在寻找一种供生物学家快速易用的高级语言。这篇博文报道了我的一些探索。虽然没有定论,但您可能仍会感兴趣。
在这里,我用几种语言(包括C、Python、Javascript、LuaJIT、Julia、Nim和Crystal)实现了两个任务,FASTQ解析和间隔重叠查询。我在比较他们的表现。我精通C语言,对Python略知一二。我使用LuaJIT和Javascript已经有几年了。我对朱莉娅、尼姆和克里斯托同样是新手。这些语言中的MyImplementation可能不是最佳的。阅读结果时,请牢记这一重要注意事项。
源代码和完整的表格可以在我的lh3/biofastgithub repo上找到。您还可以找到机器设置、正在使用的库版本和一些技术说明。我在这里只展示部分结果。
下表显示了解析gzip格式的FASTQ(T Gzip)或普通格式的FASTQ(t格式)所需的CPU时间(以秒为单位)。我们只计算序列的数量,并计算长度之和。除了这两个BioPython实现之外,其他所有实现都使用与我用C语言编写的kseq.hparser类似的算法。
该基准测试侧重于I/O和字符串处理。我替换了几种语言的低级I/O以获得良好的性能。代码看起来更像C,而不是高级语言,但至少这些语言让我不用求助于C就能获得强大的功能。
值得一提的是,默认的BioPython FASTQ解析器在普通FASTQ上慢70倍以上,在gzip的FASTQ上慢10倍以上。在人工30Xgzip的FASTQ上运行C实现需要20分钟。defaultBioPython解析器将需要四个半小时,与bwa-mem2多线程映射相当。如果您想解析FASTQ,但不需要其他BioPython功能,请选择PyFastx或mappy。
下表显示了与另一个间隔列表比较,用于计算列表间隔覆盖范围的CPU时间(以秒为单位)。计时和内存占用有两列,具体取决于加载到内存中的列表。
该算法的实现非常简单。这主要是关于对大型阵列的随机访问。JavaScript和LuaJIT在这里要慢得多,因为我不能将对象放入数组中;我只能将对对象的引用放入数组中。
以下内容是主观的,可能会引起争议,但我需要直言不讳。表现并不是一切。一些微妙但重要的细节只对那些编写这些程序的人是显而易见的。
这是两种相似的语言。它们很旧,在设计时没有考虑到即时(JIT)编译。人们后来开发了JIT编译器,并使它们变得更快。我喜欢这两种语言。它们很容易使用,性能缺陷很少,而且速度相当快。尽管如此,它们并不是生物信息学的合适语言。如果是的话,他们几年前就会占上风了。
在朱莉娅、尼姆和克里斯托这三种更现代的语言中,朱莉娅达到了1.0第一。我认为Julia可以很好地取代Matlab或R语言本身。如果你喜欢Matlab或R的体验,你可能会喜欢Julia,它有内置的矩阵支持,基于1的坐标系,友好的REPL,以及对绘图的重视。我听说它的微分方程解算器可能是所有语言中最好的。
我不认为朱莉娅是Python的好替代品。Julia的启动时间很长,当您使用Bio.jl这样的大型包时,Julia编译代码可能需要30秒,比脚本的实际运行时间要长。你可能感觉不到它在实践中速度很快。实际上,在我的基准测试中,Julia的速度也没有其他语言快。我在这里的Julia实现可能会得到最多的赞誉。我从朱莉娅的支持者那里看到了相当多的“你拿错了手机”的回复。同样重要的是,Julia开发人员并不重视向后兼容性。如果他们到那时仍然坚持自己的观点,几年后可能会出现像蟒蛇2到3这样的过渡。我不会冒这个险的。
NIM于2019年9月到期。它的语法在表面上类似于python,这是一个优点。从尼姆身上获得下降的表现相对容易些。我可能花在学习NIM上的时间最少,但我写程序的速度比Julia快。
缺点是,编写NIM程序感觉有点像编写Perl,因为我需要特别注意引用与值的关系。对于第二个任务,我的初始实现比Javascript慢好几倍,这是意想不到的。即使在当前的程序中,我仍然不明白为什么如果我在一个实例中更改为按值引用,性能会变得更差。NIM的支持者建议我运行分析器。我不确定生物学家会不会对此感到高兴。
克里斯托是个惊喜。在第二个基准测试中,我在第一次尝试时就得到了极大的满足。当我最初尝试使用Crystal的内置缓冲阅读器时,我确实绕道了FASTQ解析,但是在我开始自己管理缓冲区之后,我又一次获得了类似于C的性能。
水晶很像红宝石。它具有非常相似的语法,包括现代程序员熟悉的aclass/Mixin系统。Ruby上的一些基本教程甚至适用于Crystal。我认为建立在成功的语言之上是设计一门新语言的正确方式。另一方面,Julia给人的感觉与大多数主流语言(如C++和Python)不同。它的一些关键特性没有经受住时间的考验,可能会成为错误和性能陷阱的频繁来源。
要实现FAST程序,我们需要关心引用与值之间的关系。水晶也没什么不同。Crystal的优点是它的类系统具有明确的引用和值。在朱莉娅、尼姆和克里斯托中,我觉得克里斯托最舒服。
克里斯托并非没有问题。首先,没有root权限很难安装Crystal。我在lh3/PortableCrystal中提供了一个便携安装二进制包。它暂时缓解了这个问题。第二,水晶不稳定。每个版本都引入了多个突破性更改。您的代码编写日期稍后可能无法工作。尽管如此,我的计划似乎没有受到过去两年突破性变化的影响。这给了我一些信心。Crystal Devs还表示,1.0将“在不久的将来”问世。我期待着那一天的到来。
一种好的高水平、高性能的程序设计语言将是生物信息学领域的福音。它可以扩展生物学家的研究范围,缩短有经验的程序员的开发时间,并将大量Python脚本的运行时间节省数倍。然而,在我看来,没有一种语言是足够好的。我看看克里斯托会怎么样。它有潜力。
由Disqus提供支持的博客评论