如何运行外部代码#

本手册将引导您完成设置(可能是远程)计算资源、在计算机上设置代码以及通过 AiiDA 提交计算的步骤(与 基本教程章节 类似,但更详细)。

要使用 AiiDA 运行外部代码,你需要一个合适的 calculation plugin。在下文中,我们假设你的代码已经可以从`aiida plugin registry <https://aiidateam.github.io/aiida-registry/>`_ 获得插件,并安装在你的机器上。有关如何安装现有插件的详细信息,请参阅 如何安装插件 章节。如果您的代码还没有插件,请参阅 如何为外部代码编写插件

在整个过程中,系统会提示您提供有关计算机和代码的信息。在这些提示中

  • 键入 ?,然后键入 <enter>,以获取任何提示符下的帮助信息。

  • 随时按 <CTRL>+C 终止设置过程。你的 AiiDA 数据库将保持不变。

备注

verdi 命令使用 readline 扩展来提供默认答案,这需要使用高级终端。请使用标准终端–某些文本编辑器(如 emacs)中嵌入的终端可能会导致问题。

如何设置电脑#

AiiDA 中的 Computer 表示计算资源,您将在其上运行计算。它可以是

  1. 安装 AiiDA 的机器或

  2. 任何可以通过 SSH 从安装 AiiDA 的机器(可能是 via a proxy server)访问的机器。

第二个选项允许从同一个 AiiDA 安装管理多个远程计算资源(包括高性能计算集群和云服务),并在它们之间移动计算作业。

备注

第二个选项需要通过SSH密钥对访问。如果你的计算资源需要双因素验证,你可能需要直接在计算资源上安装 AiiDA。

计算机要求#

每台计算机必须满足以下要求:

  • 它运行类似 Unix 的操作系统(Linux 发行版和 MacOS 应可正常运行)。

  • 它安装了 bash.

  • (可选)已安装批处理调度程序(参见 支持的任务调度系统列表)。

如果要配置远程计算机,请从 配置无密码SSH登陆 开始。

备注

AiiDA 将在远程计算机上使用 bash,不管默认的 shell 是什么。请确保你的远程 bash 配置没有加载不同的 shell。

计算机设置#

计算机的配置分为两步:在 AiiDA provenance graphs 中设置与 Computer 相关的公共元数据,以及配置专用连接细节。

首先在数据库中创建一个新的计算机实例:

$ verdi computer setup

最后,该命令将打开一个文件的默认编辑器,其中包含截至目前的配置摘要。您可以添加将被执行的 bash 命令

  • 在实际执行任务之前(在 ‘执行前脚本’ 下),以及

  • 提交脚本后(在 ‘执行后脚本’ 下)。

使用这些附加行对计算机环境进行进一步设置,例如加载模块或导出环境变量:

export NEWVAR=1
source some/file

备注

不要在此指定代码或计算的特定设置:您可以在 Code 甚至 CalcJob 级设置更多执行前命令。

编辑完成后,保存并退出。现在,计算机已在数据库中创建,但您仍需使用凭据配置*访问权限。

小技巧

为了避免下次重新输入设置信息,可以通过配置文件提供部分(或全部)信息:

$ verdi computer setup --config computer.yml

其中 computer.ymlYAML format 中的配置文件。该文件包含一系列键值对信息:

---
label: "localhost"
hostname: "localhost"
transport: "core.local"
scheduler: "core.direct"
work_dir: "/home/max/.aiida_run"
mpirun_command: "mpirun -np {tot_num_mpiprocs}"
mpiprocs_per_machine: "2"
prepend_text: |
    module load mymodule
    export NEWVAR=1

yaml 文件的密钥列表由 computer setup 命令的选项提供:

$ verdi computer setup --help

注意:删除 -- 前缀,并用下划线 ( _ ) 代替按键中的破折号 (-)。

计算机连接配置#

第二步是配置专用连接的详细信息:

$ verdi computer configure TRANSPORTTYPE COMPUTERLABEL

COMPUTERLABEL 替换为设置时选择的计算机标签,将 TRANSPORTTYPE 替换为所选传输类型的名称,即 core.local 表示本地主机计算机,core.ssh 表示任何远程计算机。

完成设置和配置后,让我们检查一下一切是否正常:

$ verdi computer test COMPUTERNAME

该命令将执行各种测试,以确保 AiiDA 可以连接到计算机、在从头开始目录中创建新文件、检索文件和查询作业调度程序。

减轻连接过载#

某些计算资源,尤其是大型超级计算中心,可能无法容忍同时提交过多作业、过于频繁地执行调度程序命令或打开过多 SSH 连接。

  • 限制队列中的作业数量。

    设置要提交的 workflow 作业的最大数量限制,只有在之前的 workflow 作业开始完成后才能提交新的作业。支持的作业数量取决于超级计算机的配置,这可能是中心用户文档的一部分。超级计算机管理员也可能会发现 this page 上的信息非常有用。

  • 增加轮询作业队列的时间间隔。

    时间间隔(以秒为单位)可通过 Python API 设置,方法是加载相应的 Computer node,例如在 verdi shell 中:

    load_computer('fidis').set_minimum_job_poll_interval(30.0)
    
  • 增加连接冷却时间。

    这是打开新连接的最短等待时间(以秒为单位)。为现有计算机修改它,请使用

    verdi computer configure core.ssh --non-interactive --safe-interval <SECONDS> <COMPUTER_NAME>
    

重要

这两个时间间隔适用于每个守护进程工作者*,也就是说,工作者数量增加一倍,远程计算机的负载可能会增加一倍。

管理电脑#

配置齐全的计算机可通过以下方式列出:

$ verdi computer list

获取名为 COMPUTERLABEL 的特定计算机的详细信息:

$ verdi computer show COMPUTERLABEL

重新命名计算机或将其从数据库中删除:

$ verdi computer rename OLDCOMPUTERLABEL NEWCOMPUTERLABEL
$ verdi computer delete COMPUTERLABEL

备注

在删除 Computer 之前,你需要删除 所有 与之链接的 node(例如,任何 CalcJob``和 ``RemoteData node)。否则,AiiDA 会阻止你这样做,以保留 provenance。

如果远程计算机正在维护(或不再运行),你可能想 禁用 相应的 Computer。这样做可以防止 AiiDA 连接到指定的计算机检查计算状态或提交新的计算。

$ verdi computer disable COMPUTERLABEL
$ verdi computer enable COMPUTERLABEL

如何创建代码#

在运行一个计算之前,你需要定义一个 ``code`` 来表示计算应该执行什么代码以及如何执行。AiiDA 支持多种代码:

  • Installed:目标计算机上已安装可执行代码

  • Portable:可执行代码由 AiiDA 存储,可在各种计算机上部署

  • Containerized:可执行代码是可在目标计算机上部署和运行的容器映像的一部分

每种情况都通过代码插件提供支持,该插件存储了完全定义代码所需的所有数据。配置好的代码存储在 provenance graph 中,除了具有 import 的可重复性外,还可以轻松查询使用给定代码运行的所有计算。

备注

在大多数情况下,建议在目标机上安装AiiDA使用的可执行文件,然后*再提交使用它们的计算,以便利用目标机上的编译器和库。这就是``installed``的情况。

有时,您可能需要运行小型的、在一定程度上独立于机器的脚本(如 Python 或 bash),而手动将它们复制到多个不同的目标计算机上可能会很繁琐。在这种情况下,portable 代码是理想的选择。代码的可执行文件和相关文件由 AiiDA 保存,并在每次执行时自动复制到目标计算机。

不要**使用本地代码来封装复杂可执行文件的环境。对于这种用例,最好使用 containerized 代码。创建所需计算环境的容器,并创建容器化代码。

新代码可以通过 verdi code create 命令在 AiiDA 中配置。代码类型作为第一个参数,其余信息通过选项提供:

下面的示例显示了如何在 localhost 计算机上为 bash 二进制程序创建安装代码:

verdi code create core.code.installed \
    --label installed-code \
    --computer localhost \
    --filepath-executable /usr/bin/bash

更多信息,请参阅专用的 topic section

下面的示例显示了如何为 /path/to/directory 文件夹中的可执行文件 executable.py 创建可移植代码:

verdi code create core.code.portable \
    --label portable-code \
    --filepath-files /path/to/directory \
    --filepath-executable executable.py

属于 /path/to/directory 的任何其他文件也将由代码插件存储。

更多信息,请参阅专用的 topic section

下面的示例展示了如何通过 Singularity 在基础 Docker 容器中设置运行 bash 以在名为 some-computerComputer 上运行:

verdi code create core.code.containerized \
    --non-interactive \
    --label containerized-code \
    --computer some-computer \
    --filepath-executable "/bin/sh" \
    --image-name "docker://alpine:3" \
    --engine-command "singularity exec --bind $PWD:$PWD {image_name}"

更多信息,请参阅专用的 topic section

代码创建命令将提示输入其他选项。它还会打开文本编辑器,指定 --prepend-text--append-text 选项,您可以在其中加入将被执行的 bash 命令

  • 在运行提交脚本之前(在 ‘预执行脚本’ 行之后),以及

  • 在运行提交脚本之后(在 ‘后执行脚本’ 分隔符之后)。

例如,用它来加载模块或设置代码所需的变量,如

module load intelmpi

最后,您会收到一份确认函,其中包含新代码的 PKUUID

小技巧

verdi code create 命令执行最低限度的检查,以保持其性能,而不依赖互联网连接。如果需要额外的检查来验证代码是否正确配置和可用,请运行 verdi code test 命令。例如,对于已安装的代码,该命令将检查相关计算机是否可以连接,以及指定的可执行文件是否存在。请查看命令帮助,了解可能运行的其他检查。

小技巧

computer setup 类似,上述部分(或全部)信息可通过配置文件提供:

$ verdi code create core.code.installed --config code.yml

其中 code.ymlYAML format 中的配置文件。

该文件包含一系列键值对信息:

---
label: 'qe-6.3-pw'
description: 'quantum_espresso v6.3'
default_calc_job_plugin: 'quantumespresso.pw'
filepath_executable: '/path/to/code/pw.x'
computer: 'localhost'
prepend_text: |
   module load module1
   module load module2
append_text: ' '

yaml 文件的密钥列表由 code create 子命令的可用选项提供:

$ verdi code create core.code.installed --help

注意:删除 -- 前缀,并用下划线 ( _ ) 代替按键中的破折号 (-)。

备注

可以运行 Conda environment 提供的代码。代码配置 YAML 将如下所示:

filepath_executable: 'executable-name'
prepend_text: conda activate environment-name

请注意,配置并不完整,只显示了相关行。要使 conda activate 语句正常工作,需要在执行作业的 shell 中正确初始化该语句。

这可以通过将 Computershebang 属性配置为 #!/bin/bash -l 来实现。这将确保提交脚本使用能正确初始化 conda 的登录 shell。

如果提交脚本不应使用登录 shell(例如,因为登录 shell 会产生不必要的其他 dotfile),则可使用下面的 prepend_text 代替:

filepath_executable: 'executable-name'
prepend_text: |
    eval "$(conda shell.bash hook)"
    conda activate environment-name

更多详情,请参阅 Conda documentation

管理代码#

您可以使用以下命令更改代码的标签:

$ verdi code relabel <IDENTIFIER> "new-label"

其中 <IDENTIFIER> 可以是数字 PKUUID 或代码标签( labellabel@computername )(如果标签是唯一的)。

您还可以用以下方式列出所有可用代码及其标识符:

$ verdi code list

还可以使用标记来只过滤特定计算机上的代码,或只过滤使用特定插件的代码等(使用 -h 选项)。

您可以通过以下方式获取特定代码的信息:

$ verdi code show <IDENTIFIER>

最后,要删除代码,请使用

$ verdi code delete <IDENTIFIER>

(只有在任何计算都没有使用它的情况下,否则会出现异常)。

备注

代码是 Node 的子类,因此,您可以将 extras 附加到代码中:

load_code('<IDENTIFIER>').base.extras.set('version', '6.1')
load_code('<IDENTIFIER>').base.extras.set('family', 'cp2k')

这些信息可用于查询,例如,查找使用 6.1 或更高版本 CP2K 代码执行的所有运行。

如何提交计算#

setting up your computersetting up your code 之后,您就可以启动计算了!

  • 确保守护进程正在运行:

    verdi daemon status
    
  • 确定 CalcJob 插件需要哪些输入,例如使用

    verdi plugin list aiida.calculations core.arithmetic.add
    
  • 编写 submit.py 脚本:

    from aiida.engine import submit
    
    code = load_code('add@localhost')
    builder = code.get_builder()
    builder.x = Int(4)
    builder.y = Int(5)
    builder.metadata.options.withmpi = False
    builder.metadata.options.resources = {
        'num_machines': 1,
        'num_mpiprocs_per_machine': 1,
    
    }
    builder.metadata.description = "My first calculation."
    
    print(submit(builder))
    

    当然,代码标签和构建器输入需要根据您的代码和计算进行调整。

    备注

    另请参阅您可以传递给计算的 complete list of metadata

  • 将计算结果提交给 AiiDA 守护进程:

    verdi run submit.py
    

    之后,使用 verdi process list 监控计算状态。

小技巧

如果您需要用修改后的输入重新提交以前的计算,您可以通过以下方法获得其流程生成器的预填充副本

builder = load_node(<IDENTIFIER>).get_builder_restart()
# If needed, the builder can now be modified as usual before being run or submitted
submit(builder)

其中 <IDENTIFIER> 是您 计算PKUUID (或标签)。

详见 启动 processes监测 processes

如何监控(和提前停止)计算#

只有在下列情况下,计算作业才会终止:

  • 计算终止;可能是名义上的终止,也可能是由于错误。

  • 调度程序杀死作业,例如,由于超过挂钟时间或分配的内存已用完。

  • 计算作业通过 AiiDA 终止

如果计算似乎没有任何进展,我们可能会想要杀死计算作业,因此不是让计算自动运行到终点,而是将其杀死。通过 监控 计算作业,可以自动执行这一程序。

监视器是一个 Python 函数,在计算作业运行时会定期被调用。该函数可以访问正在运行的计算的工作目录,并检索和检查其内容。根据输出结果,它可以决定是继续运行作业还是终止作业。

如何实施监控#

监控器是一个具有以下特征的函数:

from aiida.orm import CalcJobNode
from aiida.transports import Transport

def monitor(node: CalcJobNode, transport: Transport) -> str | None:
    """Retrieve and inspect files in working directory of job to determine whether the job should be killed.

    :param node: The node representing the calculation job.
    :param transport: The transport that can be used to retrieve files from remote working directory.
    :returns: A string if the job should be killed, `None` otherwise.
    """

nodetransport 参数是必需的。 node 是对计算任务 node 的引用,例如,可用于检索其输入。 transport 可用于从远程计算机上运行的计算的工作目录中检索文件。这样就可以检查文件内容,并确定是否应提前终止计算作业。

监控器可以定义额外的关键字参数,用户可以用它们来修改或配置监控器的行为。参数可以是任何值,只要是可序列化的 JSON 值即可。这一点很有必要,因为传递给监视器的参数会存储在数据库中,以便保存 provenance。建议写出每个受支持的关键字参数,而不要使用 **kwargs 等万能参数:

from aiida.orm import CalcJobNode
from aiida.transports import Transport

def monitor(node: CalcJobNode, transport: Transport, custom_keyword: bool = False) -> str | None:
    """Retrieve and inspect files in working directory of job to determine whether the job should be killed.

    :param node: The node representing the calculation job.
    :param transport: The transport that can be used to retrieve files from remote working directory.
    :param custom_keyword: Optional keyword, when set to ``True`` will do something different.
    :returns: A string if the job should be killed, `None` otherwise.
    """

这将允许 engine 验证用户提供的参数。如果向监控器提供了不支持的参数,计算作业将无法启动,用户也会收到错误通知。

举个例子,假设有一段代码会将字符串 WARNING 打印到 stdout,在这种情况下,我们希望停止计算。下面的实现方法可以实现这一目的:

import tempfile
from aiida.orm import CalcJobNode
from aiida.transports import Transport

def monitor(node: CalcJobNode, transport: Transport) -> str | None:
    """Retrieve and inspect files in working directory of job to determine whether the job should be killed.

    :param node: The node representing the calculation job.
    :param transport: The transport that can be used to retrieve files from remote working directory.
    :returns: A string if the job should be killed, `None` otherwise.
    """
    with tempfile.NamedTemporaryFile('w+') as handle:
        transport.getfile(node.options.output_filename, handle.name)
        handle.seek(0)
        output = handle.read()

    if 'WARNING' in output:
        return 'Detected the string `WARNING` in the output file.'

本应写入 node.options.output_filename 文件的 stdout 数据流内容会使用 transport.getfile 进行检索,并写入本地文件系统上的临时文件。然后从文件中读取内容,如果检测到目标字符串,则返回错误信息。如果连接到计算任务的监视器返回的不是 None ,则 engine 将终止计算任务。

最后,需要使用 aiida.calculations.monitors 组中的 entry point 声明监控器。下一节将介绍如何使用 entry point 将其分配给计算作业。

在 2.5.0 版本加入: Monitors can now attach outputs to calculation

监控器还可以将输出附加到正在监控的计算中。这对于在计算运行时报告应永久保存在 provenance graph 中的输出非常有用。在下面的示例中,实现了一个简单的监控器,它返回一个定义了输出 nodes 字典的 CalcJobMonitorResult

from aiida.orm import CalcJobNode
from aiida.transports import Transport

def monitor(node: CalcJobNode, transport: Transport) -> CalcJobMonitorResult:
    """Return a dictionary of output nodes to be attached to the calculation to which the monitor is attached."""
    import secrets
    return CalcJobMonitorResult(
        outputs={
            'some_output': Int(2),
            'messages': {
                f'key_{secrets.token_hex(4)}': Str('some random message')
            }
        }
    )

监视器返回后,engine 将循环访问 outputs 字典中的 node,并将其连接到计算 node。请注意, CalcJob 类当然需要在输出命名空间中指定该输出端口,否则会引发异常。

如何分配监视器#

通过在 monitors 输入中添加监视器,可将其分配给计算作业。它使用监视器字典,其中每个监视器由 Dict node 定义,键如下:

monitor = Dict({
    'entry_point': 'some.monitor'
})

需要使用 entry_point 键,该键应包含 entry point,该 entry point 指向在 aiida.calculations.monitors 组中注册的监控器功能。可以为一个计算分配多个监控器:

builder = code.get_builder()
builder.monitors = {
    'monitor_a': Dict({'entry_point': 'some.monitor'}),
    'monitor_b': Dict({'entry_point': 'some.other.monitor'}),
}

请注意,monitors 输入中使用的键可以是任何有效的属性名称,不会影响任何行为。

如果监视器支持额外的自定义关键字参数,则应在 kwargs 关键字下以字典形式传递这些参数。例如,如果监控程序接受关键字 custom_keyword 的布尔值,则可按如下方式指定:

builder = code.get_builder()
builder.monitors = {
    'monitor_a': Dict({'entry_point': 'some.monitor', 'kwargs': {'custom_keyword': True}}),
}

如果指定的关键字未在监控程序中明确声明,则 CalcJob 的验证将失败。

监控执行顺序#

默认情况下,监控程序会根据 monitors 输入名称空间中的键按字母顺序执行。可以使用 monitors 输入中的 priority 键来控制顺序。

builder.monitors = {
    'monitor_one': Dict({'entry_point': 'entry_point_one', 'priority': 100})
    'monitor_one': Dict({'entry_point': 'entry_point_one'})
}

优先级较高的将优先执行。无需为所有监视器定义优先级,如果没有优先级,则假定优先级为 0。对于优先级相同的监视器,其顺序仍按字母顺序排列,以其在 monitors 输入名称空间中的键为准。

监控执行频率#

默认情况下,在每个调度程序更新周期内执行所有监控程序。该间隔由 Computerminimum_scheduler_poll_interval 属性控制,可分别通过 get_minimum_job_poll_intervalset_minimum_job_poll_interval 进行检索和设置。可以通过在监控输入定义中为 minimum_poll_interval 键设置更大的间隔来降低监控执行频率:

builder.monitors = {
    'monitor_one': Dict({'entry_point': 'entry_point_one', 'minimum_poll_interval': 600})
}

engine 将确保调用监控器的时间间隔至少为 minimum_poll_interval 所指定的值。不过,由于 CalcJob 管道中还存在一些其他间隔,因此监控器调用之间的有效间隔可能会大于该值。

高级功能#

监控器最简单的实现方式只是返回一个字符串。engine 将其解释为作业应被杀死,字符串中包含这样做的原因。可以通过返回 CalcJobMonitorResult 的实例来控制这种行为。

禁用检索文件的解析功能#

默认情况下,当通过监视器停止作业时,engine 仍将检索和解析文件。要跳过检索文件的解析,请将 CalcJobMonitorResult.parse 设置为 False

def monitor_skip_parsing(node: CalcJobNode, transport: Transport) -> str | None:
    """Kill the job and do not call the parser, if specified in the inputs."""
    from aiida.engine.processes.calcjobs.monitors import CalcJobMonitorResult
    return CalcJobMonitorResult(parse=False)

禁止检索文件#

默认情况下,当通过监视器停止作业时,engine 仍会从远程工作目录检索文件。要跳过文件检索,请将 CalcJobMonitorResult.retrieve 设置为 False

def monitor_skip_retrieval(node: CalcJobNode, transport: Transport) -> str | None:
    """Kill the job and do not retrieve the output files."""
    from aiida.engine.processes.calcjobs.monitors import CalcJobMonitorResult
    return CalcJobMonitorResult(retrieve=False, parse=False)

请注意,在这种情况下, parse 也应设置为 False ,因为 engine 无法解析尚未检索的文件。

禁用覆盖解析退出代码#

默认情况下,当通过监视器停止作业时,engine 将设置退出代码 STOPPED_BY_MONITOR 。如果调用了解析器,该代码将覆盖解析器可能返回的任何退出代码。要保留解析器的退出代码,请将 CalcJobMonitorResult.override_exit_code 设置为 False

def monitor_do_not_override_exit_code(node: CalcJobNode, transport: Transport) -> str | None:
    """Kill the job and do not override the exit code returned by the parser."""
    from aiida.engine.processes.calcjobs.monitors import CalcJobMonitorResult
    return CalcJobMonitorResult(override_exit_code=False)

禁用显示器#

默认情况下,当监视器返回除 None 以外的任何值时,engine 将立即终止作业。在某些使用情况下,监视器可能希望执行一个操作,然后让作业名义上终止,但不再调用监视器。要禁用监控器,请将 CalcJobMonitorResult.action 设置为 CalcJobMonitorActionDISABLE_SELF 选项:

def monitor_disable_self(node: CalcJobNode, transport: Transport) -> str | None:
    """Disable this monitor and let job terminate nominally."""
    from aiida.engine.processes.calcjobs.monitors import CalcJobMonitorResult, CalcJobMonitorAction
    return CalcJobMonitorResult(action=CalcJobMonitorAction.DISABLE_SELF)

所有其他监视器(如果已定义)将继续由 engine 调用。

禁用所有显示器#

默认情况下,当监视器返回除 None 以外的任何值时,engine 将立即终止作业。在某些使用情况下,监视器可能希望执行一个操作,然后让作业名义上终止。例如,监控程序会在远程工作目录中写入一个哨兵文件,让运行在远程目录中的代码优雅地自行关闭。在这种情况下,engine 最好停止调用已注册的监视器,让任务正常继续。要禁用所有监视器,请将 CalcJobMonitorResult.action 设置为 CalcJobMonitorActionDISABLE_ALL 选项:

def monitor_disable_all_monitors(node: CalcJobNode, transport: Transport) -> str | None:
    """Disable all monitors and let job terminate nominally."""
    from aiida.engine.processes.calcjobs.monitors import CalcJobMonitorResult, CalcJobMonitorAction
    return CalcJobMonitorResult(action=CalcJobMonitorAction.DISABLE_ALL)

如何利用缓存节省计算时间#

在项目过程中,您可能会多次重复运行相同的计算–可能是因为两个 workflow 包含相同的计算,也可能是因为需要重新启动因基础设施问题而失败的 workflow。

由于AiiDA存储了每个计算的全部provenance,它可以检测到一个计算是否已经被运行过,而不是再次运行,只是重复使用它的输出,从而节省宝贵的计算资源。这就是AiiDA的 缓存

启用缓存后,AiiDA 会在数据库中搜索相同的 hash 计算。如果找到,AiiDA 会创建计算 node 及其结果的副本,从而确保结果 provenance graph 与是否启用缓存无关(参见 图 3)。

../_images/caching.png

图 3 当在新的计算 C’ 中重复使用计算 C 的结果时,AiiDA 只需复制计算结果 node,并像往常一样将它们连接起来。这张图描述了相同的输入 node D1 被用于两个计算,但输入 node D1’D1 具有相同的 hash 也会触发缓存。#

缓存发生在 计算 级别(在 workflow 级别没有缓存,参见 限制与准则 )。默认情况下,成功和失败的计算在 完成 后都会进入缓存。例外和被杀死的计算 进入缓存(更多详情请参见 控制缓存 )。

如何启用缓存#

重要

默认情况下未启用缓存,请参见 the faq

缓存通过 verdi config cli 按配置文件级别进行控制。

查看当前缓存配置:

$ verdi config list caching
name                     source    value
-----------------------  --------  -------
caching.default_enabled  default   False
caching.disabled_for     default
caching.enabled_for      default

为当前配置文件或全局(所有配置文件)启用缓存:

$ verdi config set caching.default_enabled True
Success: 'caching.default_enabled' set to True for 'quicksetup' profile

$ verdi config set -g caching.default_enabled True
Success: 'caching.default_enabled' set to True globally

$ verdi config list caching
name                     source    value
-----------------------  --------  -------
caching.default_enabled  profile   True
caching.disabled_for     default
caching.enabled_for      default

在 1.6.0 版本发生变更: 从 AiiDA 1.6.0 起,通过 cache_config.yml 配置缓存已被弃用。现有的 cache_config.yml 文件将自动迁移到中央 config.json 文件。

从这一点开始,当你启动一个新的计算,AiiDA会比较它的哈希值(一个固定大小的字符串,对于一个计算的类型和输入是唯一的,见 node 如何散列 )和其他已经存在于你数据库中的计算。如果找到相同哈希值的其他计算,AiiDA 将重复使用其结果而不重复实际计算。

备注

与缓存不同的是,默认情况下***启用哈希算法,也就是说,所有计算的哈希值都已计算完毕。

如何配置缓存#

缓存机制可以在进程类级别进行配置,这意味着这些规则将自动应用于给定类的所有实例;也可以在每个实例级别进行配置,这意味着可以在启动单个进程实例时对其进行控制。

班级级别#

除了 caching.default_enabled 设置的开/关开关外,还可以使用相应的 entry point 字符串(参见 verdi plugin list aiida.calculations 的输出)在特定计算层面控制缓存:

$ verdi config set caching.disabled_for aiida.calculations:core.templatereplacer
Success: 'caching.disabled_for' set to ['aiida.calculations:core.templatereplacer'] for 'quicksetup' profile
$ verdi config set caching.enabled_for aiida.calculations:quantumespresso.pw
Success: 'caching.enabled_for' set to ['aiida.calculations:quantumespresso.pw'] for 'quicksetup' profile
$ verdi config set --append caching.enabled_for aiida.calculations:other
Success: 'caching.enabled_for' set to ['aiida.calculations:quantumespresso.pw', 'aiida.calculations:other'] for 'quicksetup' profile
$ verdi config list caching
name                     source    value
-----------------------  --------  -------------------------------------
caching.default_enabled  profile   True
caching.disabled_for     profile   aiida.calculations:core.templatereplacer
caching.enabled_for      profile   aiida.calculations:quantumespresso.pw
                                   aiida.calculations:other

在此示例中,默认情况下启用了缓存,但对于 TemplatereplacerCalculation 类计算(由相应的 aiida.calculations:core.templatereplacer entry point 字符串标识)明确禁用了缓存。它还显示了如何为特定计算启用缓存(由于是整个配置文件的默认设置,因此在这里没有影响)。

备注

如果类没有注册 entry point,也可以提供类的完整 import 路径。例如,如果类的 import 地址为 from some.module.path import SomeClass ,则可添加为

verdi config set caching.enabled_for some.module.path.SomeClass

小技巧

要同时设置多个入口点,请使用 , 分隔符。

警告

如果 verdi config set enabled_for/disabled_for 的指定值是无法加载的 entry point,或者是无法改进的路径,则会出错。

对于环境中的可用入口点,您可以使用以下命令列出已启用/禁用的入口点:

$ verdi config caching
aiida.calculations:core.arithmetic.add
aiida.calculations:core.transfer
aiida.workflows:core.arithmetic.add_multiply
aiida.workflows:core.arithmetic.multiply_add
$ verdi config caching --disabled
aiida.calculations:core.templatereplacer

对于没有 entry point 的计算,需要指定完全限定的 Python 名称。例如,定义在 aiida_quantumespresso.workflows.functions.seekpath_structure_analysis 中的 seekpath_structure_analysis calcfunction 标为 aiida_quantumespresso.workflows.functions.seekpath_structure_analysis.seekpath_structure_analysis 。从现有的 CalculationNode 中,您可以通过 process_type 属性获得标识符字符串。

缓存配置也接受 * 通配符。例如,以下配置禁用了所有计算 entry point 的缓存。

$ verdi config set caching.disabled_for 'aiida.calculations:*'
Success: 'caching.disabled_for' set to ['aiida.calculations:*'] for 'quicksetup' profile
$ verdi config caching
aiida.workflows:core.arithmetic.add_multiply
aiida.workflows:core.arithmetic.multiply_add
$ verdi config caching --disabled
aiida.calculations:core.arithmetic.add
aiida.calculations:core.transfer
aiida.calculations:core.templatereplacer

任何带通配符的条目都会被更具体的条目覆盖。以下配置禁用了除 arithmetic 以外的所有 aiida.calculation entry point 的缓存:

$ verdi config set caching.enabled_for 'aiida.calculations:core.arithmetic.*'
Success: 'caching.enabled_for' set to ['aiida.calculations:core.arithmetic.*'] for 'quicksetup' profile
$ verdi config list caching
name                     source    value
-----------------------  --------  -------------------------------
caching.default_enabled  profile   True
caching.disabled_for     profile   aiida.calculations:*
caching.enabled_for      profile   aiida.calculations:core.arithmetic.*
$ verdi config caching
aiida.calculations:core.arithmetic.add
aiida.workflows:core.arithmetic.add_multiply
aiida.workflows:core.arithmetic.multiply_add
$ verdi config caching --disabled
aiida.calculations:core.transfer
aiida.calculations:core.templatereplacer

实例级别#

无论配置文件设置如何,都可以分别使用 enable_cachingdisable_caching 上下文管理器逐个启用或禁用缓存:

from aiida.engine import run
from aiida.manage.caching import enable_caching
with enable_caching(identifier='aiida.calculations:core.templatereplacer'):
    run(...)

警告

这只会影响当前的 Python 解释器,而不会改变守护进程工作者的行为。这意味着只有在使用 run 时,此技术才有用,而***使用 submit 时则无效。

默认情况下, enable_caching 上下文管理器只会验证标识符在语法上是否有效。它 不会 验证标识符指向的类或 entry point 是否实际存在,是否可以被 imported 或加载。要确保 AiiDA 知道指定的标识符,请传递 strict=True 关键字参数:

from aiida.engine import run
from aiida.manage.caching import enable_caching
with enable_caching(identifier='aiida.calculations:core.templatereplacer', strict=True):
    run(...)

strict 设置为 True 时,如果指定的类或 entry point 无法被 imported 或加载,函数将引发 ValueError 错误。

除了控制哪些进程类被缓存外,控制哪些已*存储的 node 被用作缓存 可能是有用或必要的。第 控制缓存 节详细介绍了 AiiDA 如何决定哪些已存储的 node 等同于正在存储的 node,以及哪些被认为是有效的缓存源。

Alternatively, if the cache should not be considered for a specific process, its metadata.disable_cache input can be set to True:

from aiida.engine import submit
submit(SomeProcess, inputs={'metadata': {'disable_cache': True}})

The advantage of this approach is that the disable_cache metadata input overrides all other configuration and controls of caching, so the process is guaranteed to not be taken from the cache. Unlike the enable_caching and disable_caching context managers which only affect the local interpreter, this approach is respected by all interpreters. This approach, therefore, is mostly useful when submitting processes to the daemon that should ignore the cache.