当前位置: 首页 > 科技观察

代码老了,还能跑吗?

时间:2023-03-13 21:42:04 科技观察

NicolasRougier需要一张光盘。不是便携式U盘,也不是CD-ROM——而是一张真正的软盘。90后可能不知道软盘是一种薄而有弹性的光盘,放在方形的盒子里。外壳中间有个洞,少了一个角,可以存几百K的数据。在1983年的冷战电影《战争游戏》(战争游戏)中,高中生黑客大卫莱特曼用一张软盘黑进了学校的电脑,给了女友生物学满分。随后他黑进了军事网络,差点引发全球热核战争。Rougier的需求不那么挑衅。他只想将一个文本文件从他的Mac桌面上传到一台老式电脑——一台1977年的AppleII。这是苹果公司的第一款消费产品。Rougier是法国国家信息学与自动化研究所(INRIA)的计算神经科学家和程序员。通过这个文件是他自己的计算挑战的最后一步:十年再现性挑战(https://rescience.github.io/ten-years/)。2019年,他与法国国家科学研究中心(CNRS)理论生物物理学家KonradHinsen发起挑战,要求找到一段旧代码并重新执行,以分析基于计算的科学研究已经出版了至少十年。论文被转载。原计划让参与者在6月于波尔多举办的研讨会上讨论他们的经验,但因COVID-19而被推迟(目前暂定推迟至2021年6月)。Rougier说,虽然计算在科学中扮演着越来越重要的角色,但科学文章很少包含计算代码。即使包含了,其他人也很难实施,甚至原作者实施一段时间后也可能出现问题。编程语言在进化,代码运行的计算机环境也在进化。今天运行良好的代码明天可能会失败。2015年,Rougier和Hinsen创立了《ReScience C》。该杂志发表研究人员如何根据他们自己编写的原始论文和开源代码复制其他人的计算。然后审阅者研究代码以查看其是否有效。但即使是在这种理想化的场景下——作者愿意复现代码,审稿人精通计算领域,代码是新的——整个过程仍然有很多困难。十年代码挑战赛的目标是“找出哪些10年前编写和发布代码的技术今天仍然可用,”Hinsen说。挑战时间定在2020年1月1日,也就是Python2“退休”的日子。这种在科学领域非常流行的语言在存在20年后决定终止支持。(2008年出现的Python3还在开发中,但两者有很大区别,用一个写的代码在另一个环境下未必能运行。)“在软件世界里,十年是很长很长,longtime,”VictoriaStodden说。她在伊利诺伊大学厄巴纳-香槟分校研究计算重现性。在做出这一断言后,她表示挑战本质上是鼓励研究人员探索代码重现性的极限,是否可以在“软件世界几乎无限的时间”中复制。总共有35位挑战者。他们提出复制的43篇文章中,有28篇提交了复制报告。《ReScience C》今年早些时候开始发表他们的作品。编程语言使用的范围从C和R到Mathematica和Pascal;一位挑战者复制的不是代码,而是用系统生物学标记语言(SBML)编码的分子模型。尽管是在数字世界中,但挑战者的经验ger,就像现实世界的考古一样,可以用来汲取过去的教训,为未来的代码复现提出最佳策略。一个共同点是科学家如果想重现代码就必须优化文档。“2002年,我以为我可以永远记住一切,”威斯康星大学麦迪逊分校的生物统计学家KarlBroman说。词条复现了整个挑战中最古老的代码[1],他16岁时为AppleII写的图像放大器,发表在一本已经停刊的法国业余杂志《Tremplin Micro》(挑战中最古老的科学代码是一个用于绘制水质数据的28岁Pascal程序,后来发表于《ReScience C》)。32年后,Rougier已经记不清代码是如何工作的了,它仍然使用看起来像咒语的AppleSoftBASIC代码——“很奇怪,毕竟是我自己写的。”但他设法在网上找到代码,并用网页版的AppleII模拟器成功运行。他说,这一步相对容易,真正困难的是让它在真正的AppleII上运行。硬件不是问题——Rougier的办公室里有一台AppleII,他的同事在打扫办公室时拿起了它。“年轻人会说‘这是什么?’”他说,“然后你必须解释‘这是一台电脑’。老年人看到它会说‘哦,我对这台机器有印象’。”早在USB和互联网出现之前——现代计算机无法直接连接到旧硬盘驱动器——Rougier需要一些自制硬件,外加一盒旧软盘,让计算机读取代码。他在亚马逊上找到了这些1993年的“全新”软盘。经过三次写入以确保所有位都稳定后,他确认软盘可用。INRIA研究中心的计算机科学家BrunoLevy回顾了Rougier所写的内容。Levy也有一台AppleII,并在Twitter上发布了一段短片。老式键盘“咔嚓”一声后,调用代码,成功执行,一行纯绿色的“我们再现科研!”缓缓显示。过时的硬件,死语言当法国国家科学研究中心的生物物理化学家查尔斯·罗伯特听说这个挑战时,他决定利用这个机会回顾他多年来没有过多考虑的研究课题。“这个挑战给了我一脚,让我朝着那个方向更加努力,”他说。1995年,罗伯特使用运行商业软件Mathematica的计算笔记本对真核染色体的三维结构进行建模。罗伯特的MacBook上有Mathematica,不过为了好玩,他花100欧元(约合人民币800元)买了一台树莓派,这是一台面向爱好者的单片机,??上面安装了Linux系统,并预装了Mathematica12。Robert运行代码基本没问题,但暴露了计算笔记本可能带来的困难[2],比如缺乏代码结构,代码段也可能乱序执行。今天,罗伯特将代码分解为模块并编写代码测试。他还使用版本控制来跟踪代码的更改,并跟踪哪个版本的软件产生了什么结果。“当我阅读旧代码并思考我现在如何做得更好时,有时我会起鸡皮疙瘩,”他说,“然而,我也觉得整个过程让我回顾了从那时起我学到的一些东西.“罗伯特并不是唯一一个成功完成挑战的人:迄今为止发表的13篇复制论文中只有2篇失败了。其中一篇是由Hinsen撰写的,他在1990年代初期偶然发现了他用来系统地存储代码的磁带[3]”他说:“十年后,当你做了一个备份,却没有检查备份是否可读时,就会发生这种情况。”“在你拥有这套漂亮的磁带和备份之前,但现在你没有读取设备》(Hinsen也发表了一篇成功完成挑战的文章[4])其他没有成功完成挑战的参赛者将其归因于时间不够,尤其是在疫情之下。挑战者遇到的另一个常见问题是计算环境陈旧。计算物理学家Sabino现在在意大利国家研究委员会空气污染研究所工作的Maggi使用编程语言Fortran对称为约瑟夫森结的超导设备进行建模,并使用MicrosoftV处理结果视觉基础。从那时起,Fortran语言并没有太大变化,因此Maggi仅通过一些调整就成功地编译了代码。VisualBasic造成了更多的麻烦。“VisualBasic,”Maggi在他的文章[5]中写道,“自从被VisualBasic.NET取代以来,VisualBasic是一种死去的语言,两者之间只有相同的名称。”为了运行代码,他不得不在Mac笔记本电脑上重构一个使用了10年的Windows虚拟机。他用从网上找到的安装盘安装了MicrosoftDOS6.22和Windows3.11(都是1994年左右的软件)和VisualBasic。“即使该软件是很久以前的,使用模拟器安装受版权保护的软件仍可能存在法律问题,”美极承认。不过,因为做科研时有合法证件,他说自己觉得“至少道德上有资格”使用它。但是我应该使用哪个版本的VisualBasic?Microsoft在几年内发布了多个版本的VisualBasic,但并非所有版本都向前兼容。Maggi不记得他在1996年使用的是哪个版本,地下室的一次泄漏毁坏了他早期记录这些细节的笔记本。“我必须重新开始,”他说。在Mac上运行1994Windows模拟器以运行Microsoft的VisualBasic。资料来源:SabinoMaggiINRIA的研究工程师LudovicCourtès转载了2006年的一项研究,比较不同的数据压缩策略,用C[6]编码。但是程序员使用的应用程序编程接口(API)发生了变化,所以他的程序不能用现代软件库编译。“一切都在进化——当然,论文中使用的软件除外,”他说。最后,他不得不将六个库回滚到旧版本——他称之为“降级的连锁反应”。“坑有点深,”他说。如今,研究人员可以使用Docker容器[7]和Conda虚拟环境[8]来打包计算环境以供重用。但几位挑战者选择了另一种方式。Courtes说它“可能代表了复制科学论文的‘黄金标准’”:一个名为Guix的Linux包管理系统。它保证环境一点一点地完全可重现,并且对于代码所链接的版本是完全透明的。“整个环境,实际上是整篇论文,都可以从源代码中查看和链接,”他说。Hinsen称其“可能是迄今为止再现科学研究的最佳产品”。需要的文档在INRIA和巴黎大学的计算机科学家RobertoDiCosmo试图重现[9]的论文中,他提出了另一个挑战共同最大问题的方法:找出你把代码放在哪里。DiCosmo对1998年的一篇论文提出质疑,该论文描述了一个名为OcamlP3l的并行编程系统。他搜索了硬盘、备份,并要求他1998年的合作者也这样做,但一无所获。然后他搜索了SoftwareHeritage,这是他在2015年建立的一项服务。“找到了,太棒了,”他说。SoftwareHeritage会定期爬取Github等代码共享站点,并像InternetArchive备份网页一样备份源代码。开发者还可以要求该服务备份他们的库,挑战规则要求挑战者这样做:DiCosmo一开始没有搜索SoftwareHeritage,因为他开发OcamlP3l时它不存在。但是,我不知道是谁将他的代码发送到一个名为Gitorious的库。Gitorious现在已经没有了,但是之前有SoftwareHeritage支持,上面的OcamlP3l也包括在内。当然,找到代码并不意味着知道如何使用它。例如,Broman的文章提到,当他重现2003年的一篇论文[10]时,由于缺乏文档和“怪异”的文件结构,他在确定要运行哪些代码时遇到了很多麻烦。“我最终不得不努力阅读原始论文,”他写道。“文档(在结构良好的程序中)比代码长的情况并不少见,”加州大学伯克利分校研究计算再现性的KarthikRam说。分析方法、数据来源、数据和代码的元数据,这些都很关键。”爱丁堡大学的神经科学家梅兰妮·斯特凡(MelanieStefan)利用这项挑战来评估她用SBML编写的计算模型的可重复性。虽然代码很容易找到,但她找不到之前使用的参数(例如分子浓度)。规范化数据时的关键细节也没有得到很好的记录。结果,Stefan无法重现部分研究。“当你做研究时几乎显而易见的事情在10-12年后对你来说不再那么明显了。谁曾想到!”她嘲笑自己。可重现的光谱学Stefan的经验促使她为她的实验室制定文档规则——例如,模型必须包含如下说明:“要重现图5,请遵循以下步骤。”但Stodden说,编写这些资源需要时间。清理代码和补充文档、编写测试、清理数据集、重建计算环境——“这些都是徒劳的努力”。她补充说,研究人员没有动力去做这些事情,而且科学界对于可重现的论文应该是什么样子几乎没有达成共识。使事情更加复杂的是,计算系统不断发展,因此很难预测哪些策略将始终有效。再现性是一个光谱,曼彻斯特大学研究再现性的计算机科学家CaroleGoble说。从科学家复制他们自己的研究,到同行评审员尝试代码以证明它有效,再到研究人员将已发布的算法应用于新数据。同样,研究人员为确保可重复性所做的一系列工作(请参阅下面的“可重复性清单”),但此列表可能会很长。Goble说,把源代码放出来,至少让以后的其他人可以根据需要浏览和重写——Goble称之为“阅读代码的再现法”。“软件是有生命的,”她说,“生物最终会腐烂,因此它们需要不断修复并最终被取代。”再现性检查表虽然以下措施不能保证计算的100%再现性,但可以提高成功率。代码——如果你的计算过程是在图形界面上点击的,比如Excel,是不可重现的。将您的计算和数据操作编写为代码。文档-使用注释、计算笔记本和README文件来解释程序的工作原理,并定义预期的参数和所需的计算环境。记录-记录关键参数,例如随机数生成器的种子。此类记录可用于重现代码、查找错误和跟踪意外结果。测试-编写一套测试函数。使用阳性和阴性对照数据集来确保您获得预期的结果,并在开发过程中连续运行这些测试以立即发现编程错误。指南-编写一个主脚本(例如run.sh文件)来下载所需的数据集和变量,执行计算过程并为您的代码提供一个明显的入口点。Archive-GitHub是一个流行但非永久性的在线代码存储库。使用Zenodo、Figshare和SoftwareHeritage等存档服务来实现长期稳定性。跟踪——使用像Git这样的版本控制工具来跟踪项目历史。记录哪个版本产生了各种结果。打包-使用容器化工具(如Docker和Singularity)、在线服务(CodeOcean、Gigantum、Binder)或虚拟环境管理器(Conda)来设置一个随时可用的计算环境。自动化-使用TravisCI等持续集成服务,在各种计算环境中自动并定期测试您的代码。简化-避免稀有或难以安装的第三方代码库以简化代码重用。验证-在不同的计算环境中运行您的代码以确认其可移植性。一个不太直观的事实是,许多挑战者发现用旧语言编写的代码更容易重用。新语言的API更新频繁,它们所依赖的第三方库使得代码更容易被破坏。从这个意义上说,今年早些时候Python2.7的退役为科学家们提供了一个机会,Rougier和Hinsen说。Python2.7“让我们拥有了一种保证不会改变的高级编程语言,”Rougier写道[1]。谢菲尔德大学的研究软件工程师AnnaKrystalli说,无论研究人员使用何种编程语言和可重复性策略,对其进行测试都是明智的。Krystalli举办了一个名为ReproHacks的研讨会,研究人员在该研讨会上提交已发表的论文、代码和数据,然后要求其他参与者重现他们的结果。她说,在大多数情况下,不可能重现:作者未能提供一些对他们来说显而易见的关键细节,但其他人则没有。“无论我们在做什么,如果不实际使用和摆弄它,就不可能知道它是否真的可以重现,”Krystalli说。“这实际上比人们想象的要难得多。”