操作系统
为了让这些计算机硬件 (Hardware)相互协调地运转起来,各类软件 (Software)应运而生[1]。其中最为重要的核心程序是所谓的操作系统 (Operating system,OS),例如:Windows 、Linux [2]、BSD [3]、Solaris [4]、Android 、macOS 、iOS 和HarmonyOS 等。除Windows 外,这些系统大多深受1970年代贝尔实验室研发的UNIX 系统思想的影响。操作系统 通常由内核 (Kernel)、系统服务 和用户接口 (User Interface,UI)三部分组成组成。用户接口又分为命令解释器 (Shell、Command-Line Interpreter,CLI)和图形用户界面(Graphical User Interface,GUI)两种。

Linux内核中不同组件之间协同工作示意图。
内核 按照内核结构分类可分为宏内核 (Monolithic Kernel)、微内核 (Micro Kernel)和混合内核 (Hybrid Kernel)。它们的区别本质在于:系统功能是放在内核态 还是用户态 。宏内核 的系统功能最多,用户态 计算性能最优,但是一个组件的崩溃往往会导致整个系统的崩溃。微内核 的系统功能最少,不易崩溃,但是内核态 和用户态 的沟通开销很大。高性能计算 中一般选取宏内核 的系统,将``性能''放在首要位置。功能上,以Ubuntu24.04 LTS 系统为例,内核 主要负责进程管理 (Process Management)、内存管理 、设备驱动 (Device Driver)、文件系统 (File System)和网络协议 [5](Network Protocol)等方面。上图展示了Linux 系统内核中各主要组件协同工作的示意图[6]。系统服务 主要包含文件管理工具 (File Management Utility,例:ls、cp、mv、rm)、网络服务 (Network Service,例:httpd、sshd、udevd)、守护进程 (Daemon,例:systemd、cron)和系统库 (System library,例:glibc、libssl、libstdc++)等方面。常见的Shell 有Bash 、Csh 、Zsh [7]等。桌面环境 (Desktop Environment,包含图形界面 和一系列桌面组件。)有Gnome 、KDE Plasma 等,图形界面 需要显示服务器协议 (Display Server Protocol)来完成窗口管理与图形输出。Linux 平台上主要的显示服务器协议 有X11 (X Window System)和Wayland 。X11 是较早的客户端-服务器式窗口系统协议,Wayland 是较新的显示协议,设计更简洁,减少中间层开销。较新版本的Linux 发行版一般默认启用Wayland,但相关功能还不完善,例如利用一些远程软件访问桌面,窗口转发会有问题。
集群管理软件和分布式管理软件

分布式管理系统架构组件示意图。
管理计算机集群,就需要利用各种集群管理软件 (Cluster Management System)和分布式系统管理软件 (Distributed System Management)。前者是将计算资源进行融合,将所有的计算节点当作一个计算资源池进行管理,主要任务是节点的插入/移除、计算资源调度、计算作业排队、计算节点故障排查等。常用软件有Slurm [8]、HTCondor [9]和Torque [10]等。这些集群软件都会提供一些用户提交 、删除 和查询 作业以及查看资源使用情况等功能;后者是在资源池上运行各种服务,让多台机器在逻辑上表现为一个统一系统,并保证一致性、容错性和可扩展性。如图所示,分布式系统框架 或中间件 (Distributed System Framework/Middleware)主要有[11]Ambari (系统管理层)、ZooKeeper (协调层)、Hadoop (计算框架)、Spark (大数据处理框架)、HDFS (存储系统)、Kafka(分布式消息流平台)等。除了这些比较宏观的管理软件外,还有很多配件和更底层的系统,这里就不再赘述。
编程辅助工具简介
版本控制工具
除了操作系统层面的选择,为了管理大体量的代码工程,需要版本控制工具 (Version Control System,VCS),例如SVN [12](Subversion)、Git [13]和Fossil [14]等。这些工具可以很方便地获取和提交代码、查询历史更改记录、代码合并等。其中Git 软件最初是Linus Torvalds[15]为了为替代BitKeeper 工具,维护Linux 内核源码而开发设计的工具。即便只是自己一个人开发的小项目,当程序出现错误时,也可很方便通过版本回溯(Version Rollback)快速定位问题来源,提高调试效率。
Git简介

Git软件的基本指令使用示意图。
这里简单介绍一下Git 工具的使用,上图展示了Git 常用的几个命令和4个工作区域。其中工作目录 (Workspace)即是常规写代码的地方。当在工作环境 中添加了新的文件或修改了内容,则可通过add 命令,将变动后的内容提交到暂存区 (Staging Area)。当代码都测试完成没有问题,就可用commit 将变动的内容提交到本地仓库 (Local Repository)。当一个版本的代码都执行完成后,则可通过push 命令提交到远程仓库 (Remote Repository),如果只是自己一个人写代码,没有远程仓库 需要,代码保存在本地仓库 即可。一份代码若是多人在维护,则需通过pull 命令获取远程更改。如果测试代码有问题,则可通过restore 或reset 命令从暂存区 或本地仓库 回退代码到工作目录 。往往从远程仓库clone 下来的项目有多个分支 (Branch,版本),需要通过checkout 命令选取具体的分支再进行操作。以上命令大多可通过可视化工具GitHub Desktop [16]、SourceTree [17]等进行。工具中可以直观的看到提交更改历史,代码增减情况。除版本控制工具外,软件开发过程中还需要用到敏捷开发 (DevOps)、持续集成 (Continuous Integration,CI)和持续交付/部署(Continuous Delivery/Deployment,CD)等工具。基础科研中代码量和开发者数量一般不会大到需要用这些工具的程度,所以这里不展开描述。
应用容器
还有一个常用的工具是所谓的应用容器 (Application Container)。常见的有Docker [18]、Apptainer [19]、Charliecloud [20]等。Docker 创建了一个标准化的开发环境,无需在本地机器上安装各种依赖项,且容器保证应用程序和其依赖在开发、测试和生产环境中表现一致。对于科研人员来说,许多软件也提供了容器镜像 (Container Image),这使得软件的安装和使用变得更加简便。然而,由于Docker 需要超管权限 (root)来运行和管理容器,因此存在一定的安全漏洞。一般来说,若高校服务器使用了Docker ,网信办可能会自动断开服务器的网络连接,仅允许其在单机模式下使用。作为替代品,Apptainer 逐渐得到广泛应用,尤其在高性能计算 (High Performance Computing,HPC)和科研领域 中。Apptainer 可以在无root用户权限 下运行,这意味着科研人员和开发者无需管理员权限即可构建、运行和部署容器,这对许多无法获得管理员权限的高性能计算集群或共享计算环境非常方便。此外,Apptainer 容器内的应用可以与宿主机完全隔离,从而提供更强的隔离性 。如今,一些服务器管理系统,如HTCondor 和Slurm ,也支持通过容器镜像提交计算任务,尤其当操作系统本身缺乏某些依赖环境时,容器的隔离性也不会破坏原有的运行环境。
编程语言类型
一开始,人们在计算机上编写并运行的程序主要由数字0和1组成的机器码 [21](Machine Code),随后,人们为了提高可读性 与编程效率 ,发展出了所谓的汇编语言 (Assembly Language)。早期汇编语言 本质上是机器指令的助记符 表示形式,由汇编器 (Assembler)将其转换为对应的机器码 。再后来,又发展出了抽象程度更高的高级编程语言 (High-level Programming Language)。第一种高级编程语言为Fortran [22],它由IBM 公司于1957年正式发布。随着时间推移,针对不同应用需求,逐渐衍生出各种特定用途或领域导向的编程语言,例如用于科学计算、数据库查询、网页开发等。为保证语言实现的一致性与可移植性,也相应制定了多种语言标准与规范(Language Standard,Specification)。
语言标准与规范
| 规范 | 说明 |
| 词法结构 | 规定程序的最小组成单位(Token)是什么,包括:字符集(ASCII/Unicode等)、关键字(Keyword)、运算符(Operator)、分隔符(Delimiter)、字面量形式(Literal,浮点、整型、字符串等)以及标识符规则等。 |
| 语法 | 规定Token如何组合成合法程序,通常用BNF/EBNF描述。 |
| 语义 | 规定程序``运行时到底做什么''。通常分为三类:操作语义(程序如何运行)、指称语义(程序是什么函数)、公理语义(程序是否满足某性质)。 |
| 类型系统 | 规定:有哪些数据类型、类型之间是否可转换、类型检查规则、静态/动态类型等。例如:基本类型(int, float)、复合类型(struct, class)、泛型机制等。 |
| 运行时模型 | 规定程序执行时环境结构,例如:内存模型、栈与堆(Stack \& Heap)、变量生命周期(Lifetime)、作用域规则、并发模型等。 |
| 约束与未定义行为 | 这第一点关系到语言的可优化程度、可移植性等方面,通常分为未定义行为(Undefined Behavior,UB,越界、溢出等)、实现定义行为(Implementation-defined Behavior,文档中需说明的操作,例如负数右移结果)、未指定行为(Unspecified Behavior,可能有多种合法结果)三类行为。 |
| 标准库接口 | 标准库一般包含:输入输出(I/O)、字符串处理、容器(Container)、数学函数、多线程支持(Multithreading)。例如Python就含有非常丰富的标准库,而Fortran只有科学计算相关的一些函数。 |
|---|
如表所示,语言标准与规范 本身规定了某种具体编程语言的词法结构 (Lexical Structure)、语法 (Grammar)、语义 (Semantics)、类型系统 (Type System)、运行时模型 (Runtime Model)、约束与未定义行为 (Constraints & Undefined Behavior)以及标准库接口 (Standard Library Interface)等内容。这类语言标准通常由国际标准化组织或语言标准委员会制定,并定期进行更新。例如C++ 语言的一次里程碑式更新------C++11 标准,于2011年正式发布,引入了自动类型推导(auto)、右值引用、并发库等大量新特性。
语言实现
在语言规范 确立之后,国际上一些公司或开源基金会依据规范实现对应语言的编译器或解释器等工具,即所谓的语言实现 (Language Implementation)。这些具体实现通常不仅满足标准要求,还可能包含一定数量的扩展特性 (Extension),因此在语法或功能上可能``超出''标准规范所定义的范围。例如:C 语言具的常见实现包括:Intel 公司实现的C 语言编译器、GNU (GNU's Not Unix的递归缩写)维护的自由软件项目GCC [23]、隶属LLVM 项目的Clang [24]等;Python 的常见实现包括:CPython [25]、IronPython [26]、Jython [27]、PyPy [28]等;Fortran 的实现包括:GFortran [29]、Flang [30]、ifort[31]。在语言标准委员会讨论和制定新标准时,往往已有部分厂商或开源社区在实践中实现了某些新特性,这些既有实现经验也会反过来推动标准的演进。