create_test 命令提供了一个强大的工具,能够测试一个案例。该命令可以根据 testname 语法创建、设置、构建和运行一个案例,并返回通过或失败的结果。
单个测试可以运行为:
$CIMEROOT/scripts/create_test <testname>
测试将执行的所有操作都由 testname 控制。
10.1. 测试名称语法
测试的格式定义如下,其中 []
内的任何内容都是可选的:
TESTTYPE[_MODIFIERS].GRID.COMPSET[.MACHINE_COMPILER][.GROUP-TESTMODS]
例如使用最小的 TESTTYPE 、GRID 和 COMPSET :
ERP.ne4pg2_oQU480.F2010
以下是 testname
语法的不同部分的分解说明。
名称部分 | |
---|---|
TESTTYPE | 测试的通用类型,例如 SMS。选项列在以下表格和 config_tests.xml 中。 |
MODIFIERS | 测试类型的默认设置更改。参见以下表格和 test_scheduler.py。 |
GRID | 网格集(通常是网格别名)。 |
COMPSET | 组件集,可以是长名称,但通常是组件集别名。 |
MACHINE | 这是可选的;如果未提供此值,create_test 将探测底层机器。 |
COMPILER | 如果未提供此值,则使用 MACHINE 的默认编译器。 |
GROUP-TESTMODS | 这是可选的。这指向一个包含 user_nl_xxx 文件或可用来在运行测试前制作 namelist 和其他修改的 shell_commands 的目录。 |
10.1.1. 测试类型
CIME 中的测试类型都是系统测试:它们会编译案例中所需的全部代码,测试模型的功能,例如重启能力、与 MPI 任务数量的不变性以及短期归档。目前,它们不测试科学上的正确性。
当前支持的测试类型有:
TESTTYPE | 描述 |
---|---|
ERS | 从启动时精确重启(默认 6 天+5 天) 进行一个 11 天的初始测试 - 在第 6 天写一个重启文件。(文件后缀:base) 进行一个 5 天的重启测试,从第 6 天开始重启。(文件后缀:rest) 在第 11 天使用 cprnc 比较组件历史文件“.base”和“.rest” PASS if they are identical. 如果它们相同,则通过。 |
ERS2 | 从启动时精确重启(默认 6 天+5 天)。 进行 11 天的初始测试,不进行重启。(文件后缀:base) 进行 11 天的重启测试,在第 6 天重启后停止,然后从第 6 天重启处继续。(文件后缀:rest) 在第 11 天比较组件历史文件“.base”和“.rest”。 |
ERT | ERS 的更长版本。从启动时精确重启,默认 2 个月+1 个月(ERS,信息 DBUG=1)。 |
IRT | 从启动时精确重启,默认 4 天+7 天,从中间文件重启。 |
ERIO | 从启动时精确重启,使用不同 IO 文件类型,默认 6 天+5 天。 |
ERR | 从启动时精确重启,使用重新提交,默认 4 天+3 天。 |
ERRI | 从启动时精确重启,使用重新提交,(默认 4 天+3 天)。测试 st_archive 的不完整日志选项。 |
ERI | 混合/分支/精确重启测试,(默认 STOP_N 是 22 天) ref1case 进行 3 天的初始运行,在第 3 天写入重启。ref1case 是主案例的克隆。短期归档已开启。 ref2case (Suffix hybrid) ref2case(后缀混合) 进行混合运行,默认运行 19 天,从第 3 天使用 ref1 的重新启动,并在第 10 天写入重新启动。ref2case 是主案例的克隆。短期归档已开启。 case 进行分支运行,从 ref2case 中写入的重新启动开始,运行 9 天,并在第 5 天写入重新启动。短期归档已关闭。 case(后缀 base) 从 4 天的分支运行重启中执行重启运行。在第 19 天比较组件历史文件‘.base’和‘.hybrid’。短期归档已关闭。 |
ERP | PES 按位测试混合(OPENMP/MPI)重启,从启动开始计数(默认 6 天 + 5 天)。 初始 PES 开箱即用执行 11 天的初始测试 - 在第 6 天写入重启。(文件后缀 base)每个组件的任务和线程数减半。从第 6 天的重启开始执行 5 天的重启测试。(文件后缀 rest)在第 11 天比较组件历史文件‘.base’和‘.rest’。这就像一个 ERS 测试,但重启时的任务/线程计数被修改。 |
PEA | 单个 PE 按位测试(默认 5 天) 在 1 个 PE 上使用 mpi 库进行初始运行。(文件后缀:base)在 1 个 PE 上使用 mpi-serial 库进行相同的运行。(文件后缀:mpi-serial)比较 base 和 mpi-serial。 |
PEM | 修改 PE 数量用于 MPI(NTASKS)逐位测试(默认 5 天) 使用默认 PE 布局进行初始运行(文件后缀:base)使用修改后的 PE 布局进行另一个初始运行(NTASKS_XXX => NTASKS_XXX/2)(文件后缀:modpes)比较 base 和 modpes |
PET | 修改线程的 OPENMP 逐位测试(默认 5 天) 进行一次初始运行,其中所有组件默认都是线程化的。(文件后缀:base)再进行另一次初始运行,其中所有组件的 NTHRDS=1。(文件后缀:single_thread)比较 base 和 single_thread。 |
PFS | 性能测试设置。历史和重启输出被关闭。(默认 20 天) |
ICP | CICE 性能测试。 |
OCP | POP 性能测试。(默认 10 天) |
MCC | 多驱动器验证与单驱动器(均为多实例)。(默认 5 天) |
NCK | 多实例验证与单实例 - 实例的顺序 PE(默认长度) 使用 NINST 1 进行初始运行测试。(文件后缀:base)使用 NINST 2 进行初始运行测试。(文件后缀:多实例,适用于_0001 和_0002)比较 base、_0001 和_0002。 |
REP | 可重复性:两次相同的初始运行是完全一致的。(默认 5 天) |
SBN | 烟雾测试构建 namelist(只需运行 preview_namelist 并检查输入数据)。 |
SMS | 烟雾测试(默认 5 天) 进行为期 5 天的初始测试,确保测试运行至完成且无错误。(文件后缀:base) |
SEQ | 进行为期 5 天的初始测试,确保测试运行至完成且无错误。(文件后缀:base) 使用开箱即用的 PE 布局进行初始运行测试。(文件后缀:base)进行第二次运行,所有根 PE 都在 pe-0。(文件后缀:seq)比较 base 和 seq。 |
DAE | 数据同化测试,默认 1 天,两个 DA 周期,无数据修改。 |
PRE | 暂停-恢复测试:默认逐位测试暂停-恢复循环。 默认 5 小时,五次暂停/继续循环,不修改数据。 |
测试将按照上述默认长度运行,将使用测试运行机器及其默认耦合器和 MPI 库的默认 pelayouts。可以通过测试类型修改器修改测试的元素。
10.1.2. 修饰符
MODIFIERS | 描述 |
---|---|
_C# | 设置实例数量为 # 并使用多驱动器(不能与 _N 一起使用)。 |
_CG | CALENDAR 设置为“公历” |
_D | XML 变量 DEBUG 设置为“TRUE” |
_I | 用于区分同名测试的标记 - 表示忽略。 |
_Lo# | 运行长度由 o(STOP_OPTION)和#(STOP_N)设置。 o = {“y”:”nyears”, “m”:”nmonths”, “d”:”ndays”, |
“h”:”nhours”, “s”:”nseconds”, “n”:”nsteps”} | |
_Mx | 将 MPI 库设置为 x。 |
_N# | 将实例数量设置为#,并使用单个驱动(不能与_C 一起使用)。 |
_Px | 将 create_newcase 的 --pecount 设置为 x,通常是 N(任务)或 NxM(每个任务的线程数)。 |
_R | 用于 PTS_MODE 或单列模型(SCM)模式下的测试。对于 PTS_MODE,使用 mpi-serial 编译。 |
_Vx | 将驱动器设置为 x。 |
例如,这将在编译时开启调试模式运行 ERP 测试:
$CIMEROOT/scripts/create_test ERP_D.ne4pg2_oQU480.F2010
这将运行 ERP 测试 3 天而不是默认的 11 天:
$CIMEROOT/scripts/create_test ERP_Ld3.ne4pg2_oQU480.F2010
您可以组合测试类型修饰符:
$CIMEROOT/scripts/create_test ERP_D_Ld3.ne4pg2_oQU480.F2010
10.1.3. 组测试修饰符
create_test 命令使用现成的 compsets 和 grid sets 运行。有时你可能希望在不创建整个 compset 的情况下,通过修改 namelist 或其他设置来运行一个测试。案例控制系统(CCS)为此情况提供了 testmods 功能。
GROUP-TESTMODS
字符串位于完整的 testname (包括机器和编译器)的末尾。GROUP-TESTMODS
的解析形式如下。
PART | 描述 |
---|---|
GROUP | TESTS_MODS_DIR 下包含 TESTMODS 的目录名称。 |
TESTMODS | 任何在 GROUP 目录下的目录中 user_nl_*、shell_commands、user_mods 或 params.py 的组合。 |
例如,可以通过使用 eam-rrtmgp
来修改 E3SM F-case 的 ERP 测试,以使用不同的辐射方案:
ERP_D_Ld3.ne4pg2_oQU480.F2010.pm-cpu_intel.eam-rrtmgp
如果 TESTS_MODS_DIR
被设置为 $E3SM/components/eam/cime_config/testdefs/testmods_dirs
,则包含测试模块的目录将是 $E3SM/components/eam/cime_config/testdefs/testmods_dirs/eam/rrtmpg
。
在这个目录中,你会找到一个名为 shell_commands 的文件,其中包含以下内容:
#!/bin/bash
./xmlchange --append CAM_CONFIG_OPTS='-rad rrtmgp'
这些命令在测试用例创建后,调用 case.setup 时才会应用。
注意:不要在测试模块目录名称中使用“-”,因为它在 create_test 中有特殊含义。
10.1.3.1. user_nl_<component> 示例
可以通过在 GROUP-TESTMODS 目录中提供 user_nl_*
文件来修改组件的 namelist。例如,要更改 eam 组件的 namelist,可以使用文件名 user_nl_eam
。
# user_nl_eam
deep_scheme = 'off',
zmconv_microp = .false.
shallow_scheme = 'CLUBB_SGS',
l_tracer_aero = .false.
l_rayleigh = .false.
l_gw_drag = .false.
l_ac_energy_chk = .true.
l_bc_energy_fix = .true.
l_dry_adj = .false.
l_st_mac = .true.
l_st_mic = .false.
l_rad = .false.
10.1.3.2. shell_commands 示例
通过在 GROUP-TESTMODS 目录中提供一个 shell_commands
文件,可以修改测试。这个 shell 文件可以包含任何任意的命令,例如:
# shell_commands
#!/bin/bash
# Remove exe if chem pp exe (campp) already exists (it ensures that exe is always built)
/bin/rm -f $CIMEROOT/../components/eam/chem_proc/campp
# Invoke campp (using v3 mechanism file)
./xmlchange --append CAM_CONFIG_OPTS='-usr_mech_infile $CIMEROOT/../components/eam/chem_proc/inputs/pp_chemUCI_linozv3_mam5_vbs.in'
# Assuming atmchange is available via $PATH
atmchange initial_conditions::perturbation_random_seed = 32
10.1.3.3. user_mods 示例
通过在 GROUP-TESTMODS 目录中提供一个 user_mods
文件中的列表,可以应用额外的 GROUP_TESTMODS_ 。
# user_mods
eam/cosp
eam/hommexx
10.1.3.4. params.py 示例
支持的 TESTYPES_ 可以通过在 GROUP-TESTMODS 目录中提供一个 params.py
文件来进一步修改。
10.1.3.4.1. MVK
MVK 系统测试可以通过在 params.py
中定义 变量 和 方法 来配置。
参见示例 了解简单和复杂的使用案例。
10.1.3.4.1.1. 变量
变量 | 默认 | 类型 | 描述 |
---|---|---|---|
component | str | 主要组件 | |
components | [] | list | 需要 namelist 自定义的组件 |
ninst | 30 | int | 实例的数量 |
var_set | default | str | 要分析的变量集的名称 |
ref_case | Baseline | str | 参考案例的名称 |
test_case | Test | str | 测试用例的名称 |
10.1.3.4.1.2. 方法
def evv_test_config(case, config):
"""
Customize the evv4esm configuration.
This method is used to customize the default evv4esm configuration
or generate a completely new one.
The return configuration will be written to `$RUNDIR/$CASE.json`.
Args:
case (CIME.case.case.Case): The case instance.
config (dict): Default evv4esm configuration.
Returns:
dict: Dictionary with test configuration.
"""
def generate_namelist(case, component, i, filename):
"""
Generate per instance namelist.
This method is called for each instance to generate the desired
modifications.
Args:
case (CIME.case.case.Case): The case instance.
component (str): Component the namelist belongs to.
i (int): Instance unique number.
filename (str): Name of the namelist that needs to be created.
"""
10.1.3.4.1.3. 示例
最简单的情况下,只需要在 params.py
中定义变量 。
对于这种情况,将调用默认的 evv_test_config
和 generate_namelist
函数。
component = "eam"
# components = [] can be omitted when modifying a single component
ninst = 10
如果需要更多对 evv4esm 配置文件或每个实例配置的控制,那么可以在 params.py
文件中重写 evv_test_config
和 generate_namelist
函数。
变量仍然需要定义以生成默认的 evv4esm 配置或 evv_test_config 函数中的 config
,也可以忽略 evv_test_config
函数中的配置,并返回一个全新的字典。
在以下示例中,默认的 module
、component
和 ninst
都被更改。generate_namelist
函数为某些组件创建 namelists,同时运行 shell 命令来定制其他组件。
注意:这是一个玩具示例,没有科学用途。
import os
from CIME.SystemTests.mvk import EVV_LIB_DIR
from CIME.namelist import Namelist
from CIME.utils import safe_copy
from CIME.utils import run_cmd
component "eam"
# The generate_namelist function will be called `ninst` times per component
components = ["eam", "clm", "eamxx"]
ninst = 30
# This can be omitted if the default evv4esm configuration is sufficient
def evv_test_config(case, config):
config["module"] = os.path.join(EVV_LIB_DIR, "extensions", "kso.py")
config["component"] = "clm"
config["ninst"] = 20
return config
def generate_namelist(case, component, i, filename):
namelist = Namelist()
if component in ["eam", "clm"]:
with namelist(filename) as nml:
if component == "eam":
# arguments group, key, value
nml.set_variable_value("", "eam_specific", f"perturn-{i}")
elif component == "clm":
if i % 2 == 0:
nml.set_variable_value("", "clm_specific", "even")
else:
nml.set_variable_value("", "clm_specific", "odd")
else:
stat, output, err = run_cmd(f"atmchange initial_conditions::perturbation_random_seed = {i*32}")
safe_copy("namelist_scream.xml", f"namelist_scream_{i:04}.xml")
10.2. 测试进度和输出
每个由 create_test 执行的测试运行包括以下必经步骤:
-
CREATE_NEWCASE: 创建创建
-
XML: 根据测试设置对用例进行 xml 更改
-
SETUP:设置案例(case.setup)
-
SHAREDLIB_BUILD:构建共享库
-
MODEL_BUILD:构建模块(case.build)
-
SUBMIT:提交测试(case.submit)
-
RUN:运行测试测试
以及以下可选阶段:
-
NLCOMP:比较案例名称列表与基线
-
THROUGHPUT:与基准吞吐量进行比较
-
MEMCOMP:比较内存使用与基线内存使用
-
MEMLEAK:检查内存泄漏
-
COMPARE: 用于跟踪特定测试的比较,例如,一个 ERS 测试会有一个 COMPARE_base_rest 阶段,表示检查基础结果是否与重启结果匹配。
-
GENERATE: 生成基准结果
-
BASELINE: 将结果与基准进行比较
测试中的每个阶段可能处于以下状态之一:
-
PASS:该阶段已成功执行
-
FAIL:我们尝试执行此阶段,但失败了。如果此阶段是强制的,则此测试将不会继续进行。失败详情应记录在 TestStatus.log 中。
-
PEND:此阶段将运行或正在运行但未完成
10.3. 运行多个测试和其他命令行示例
可以通过在命令行上列出所有测试名称来运行多个测试:
$CIMEROOT/scripts/create_test $test_name $test_name2
或者将测试名称放入文件中,每行一个名称:
$CIMEROOT/scripts/create_test -f $file_of_test_names
要使用非默认编译器运行测试:
./create_test SMS.f19_f19.A --compiler intel
要运行一个与基准名称“master”进行对比的测试:
./create_test SMS.f19_f19.A -c -b master
要运行一个测试并使用基准名称“master”更新基准:
./create_test SMS.f19_f19.A -g -b master
要使用非默认的测试 ID 运行测试:
./create_test SMS.f19_f19.A -t my_test_id
要运行一个测试并使用您用例目录的非默认测试根目录:
./create_test SMS.f19_f19.A -t $test_root
要运行测试并使用和放置案例、构建和运行目录都在同一个根目录下:
./create_test SMS.f19_f19.A --output-root $output_root
要运行测试并强制它进入某个特定的批处理队列:
./create_test SMS.f19_f19.A -q myqueue
案例控制系统支持更复杂的方式来指定一组测试以及它们应该如何运行。一种方法使用 XML 文件,另一种方法使用 Python 字典。
10.4. 使用 XML 文件进行测试控制
一个预定义的测试套件可以通过使用 --xml
选项来运行 create_test,该选项从 testlist*.xml 文件中收集测试名称。正如在 https://github.com/ESCOMP/ctsm/wiki/System-Testing-Guide 中所述,要确定有哪些预定义的测试套件可用以及它们包含哪些测试,您可以通过运行 query_testlists 来实现。
在 create_test 中,测试套件通过 3 个选择属性检索:
--xml-category your_category The test category.
--xml-machine your_machine The machine.
--xml-compiler your_compiler The compiler.
如果这 3 个都不使用,默认值是“none”。
如果使用了其中任何一个,未使用选项的默认值是“all”。
这些属性的现有值可以通过运行 query_testlists 查看。
搜索测试名称可以限制为单个测试列表,使用:
--xml-testlist your_testlist
省略此选项会导致搜索在 中列出的所有测试列表:
cime/config/{cesm,e3sm}/config_files.xml
$CIMEROOT/scripts/query_testlists 收集 XML 格式的测试和测试列表的描述、组件和项目。
--xml-{compiler,machine,category,testlist}
参数可用于聚焦搜索,就像在 create_test(上文)中那样。测试的“category”描述符可用于同时运行一组关联测试。可用的类别及其包含的测试可以通过以下方式列出:
./query_testlists --define-testtypes
--show-options
参数执行相同操作,但会显示为测试定义的“选项”,例如队列、墙时间等。
添加测试需要首先决定要测试哪个 compset,然后找到相应的 testlist_$component.xml 文件:
components/$component/cime_config/testdefs/
testlist_$component.xml
testmods_dirs/$component/{TESTMODS1,TESTMODS2,...}
cime_config/
testlist_allactive.xml
testmods_dirs/allactive/{defaultio,...}
你可以在 testmods_dirs 中为该测试可选地添加 testmods。测试列表和 testmods 在 cime、drv 和组件中位于不同的路径。
如果这个测试将只作为一个单独的测试运行,你现在可以创建一个测试名称,并遵循单独 的测试说明来创建测试。
10.5. 使用 python 字典进行测试控制
也可以在一个名为 tests.py 的文件中定义测试套件,该文件通常位于$MODEL/cime_config/tests.py
要运行名为 e3sm_developer 的测试套件:
./create_test e3sm_developer
可以将特定的测试从测试套件中排除:
./create_test e3sm_developer ^SMS.f19_f19.A
有关完整选项列表,请参阅 create_test -h
要添加测试,请打开 MODEL/cime_config/tests.py 文件,您会在文件顶部看到一个名为 _TESTS 的 Python 字典,在这个字典中找到您要更改的测试类别,并将您的测试用例添加到列表中。注意该文件顶部注释中说明您需要以 test>.. 的格式添加测试,然后还有一个 mods 的第二个参数。机器和编译器会根据 create_test 被调用的位置及其参数稍后添加。
可以使用 cime/CIME/Tools/list_e3sm_tests 脚本来列出现有测试。
例如:
./list_e3sm_tests -t compsets e3sm_developer
将列出 e3sm_developer 测试套件中测试的所有 compsets。
10.6. 创建测试输出
解释测试输出非常简单。以一个示例来看:
$ ./create_test SMS.f19_f19.A
Creating test directory /home/jgfouca/e3sm/scratch/SMS.f19_f19.A.melvin_gnu.20170504_163152_31aahy
RUNNING TESTS:
SMS.f19_f19.A.melvin_gnu
Starting CREATE_NEWCASE for test SMS.f19_f19.A.melvin_gnu with 1 procs
Finished CREATE_NEWCASE for test SMS.f19_f19.A.melvin_gnu in 4.170537 seconds (PASS)
Starting XML for test SMS.f19_f19.A.melvin_gnu with 1 procs
Finished XML for test SMS.f19_f19.A.melvin_gnu in 0.735993 seconds (PASS)
Starting SETUP for test SMS.f19_f19.A.melvin_gnu with 1 procs
Finished SETUP for test SMS.f19_f19.A.melvin_gnu in 11.544286 seconds (PASS)
Starting SHAREDLIB_BUILD for test SMS.f19_f19.A.melvin_gnu with 1 procs
Finished SHAREDLIB_BUILD for test SMS.f19_f19.A.melvin_gnu in 82.670667 seconds (PASS)
Starting MODEL_BUILD for test SMS.f19_f19.A.melvin_gnu with 4 procs
Finished MODEL_BUILD for test SMS.f19_f19.A.melvin_gnu in 18.613263 seconds (PASS)
Starting RUN for test SMS.f19_f19.A.melvin_gnu with 64 procs
Finished RUN for test SMS.f19_f19.A.melvin_gnu in 35.068546 seconds (PASS). [COMPLETED 1 of 1]
At test-scheduler close, state is:
PASS SMS.f19_f19.A.melvin_gnu RUN
Case dir: /home/jgfouca/e3sm/scratch/SMS.f19_f19.A.melvin_gnu.20170504_163152_31aahy
test-scheduler took 154.780044079 seconds
你可以看到 create_test 会告知用户案例目录以及各个测试阶段进度和持续时间。
测试的$CASEDIR 将在$CIME_OUTPUT_ROOT 中创建。名称将采用以下形式:
TESTTYPE[_MODIFIERS].GRID.COMPSET.MACHINE_COMPILER[.GROUP-TESTMODS].YYYYMMDD_HHMMSS_hash
如果使用了 MODIFIERS 或 GROUP-TESTMODS,这些内容将被包含在测试输出目录名称中。附加的 YYYYMMDD_HHMMSS_hash 字符串是测试 ID,用于区分同一测试的多次运行。该字符串可以通过 create_test 的–test-id 参数进行替换。
对于测试, $CASEDIR 将包含 $EXEROOT 和 $RUNDIR 作为子目录。
测试的当前状态表示在文件 $CASEDIR/TestStatus 中。示例输出:
PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel CREATE_NEWCASE
PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel XML
PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel SETUP
PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel SHAREDLIB_BUILD time=277
PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel MODEL_BUILD time=572
PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel SUBMIT
PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel RUN time=208
PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel COMPARE_base_rest
PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel MEMLEAK insufficient data for memleak test
PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel SHORT_TERM_ARCHIVER
运行此测试时,CIME 案例控制系统产生的所有其他标准输出将放入文件 $CASEDIR/TestStatus.log 中
还将把一个 cs.status.$testid 脚本放入测试根目录。该脚本将允许你查看.
10.7. 基线和基线测试
测试的一个重要部分是管理你的基线(有时称为黄金结果),并对基线进行额外测试。测试的基线将是测试运行中创建的(历史)文件的副本。
create_test 可以被要求对当前测试运行生成的文件和基线中存储的文件进行逐位比较。对于基线测试通过,它们必须逐位完全相同。
基线测试为来自测试类型的测试标准添加了一个额外的测试标准,并用作防止无意中改变确定性气候模型结果的一种方式。
10.7.1. 创建基线
基线可以通过向 create_test 传递 -g
来生成。还有其他选项用于控制生成基线。:
./scripts/create_test -b master -g SMS.ne30_f19_g16_rx1.A
10.7.2. 与基线比较
通过向 create_test 传递 -c
,可以将测试输出与基线进行比较。:
./scripts/create_test -b master -c SMS.ne30_f19_g16_rx1.A
假设你在源代码中不小心更改了某些内容,这不会导致模型崩溃,但会导致模型改变它生成的答案。在这种情况下,SMS 测试会通过(它仍然运行),但与基线的比较会失败(答案与基线不是逐位相同的),因此整个测试会失败。
10.7.3. 管理基线
如果你打算更改答案,需要用新文件更新基线。这被称为“认可”测试。这是通过 bless_test_results 工具完成的。该工具提供了认可基线不同功能的能力。目前支持的功能包括 namelist 文件、历史文件和性能指标。性能指标分为吞吐量和内存使用。
可以使用以下命令将测试与基线进行比较,并认可对历史文件的更新:
./CIME/Tools/bless_test_results -b master --hist-only SMS.ne30_f19_g16_rx1.A
可以使用 <../Tools_user/compare_test_results.html>_ 工具快速比较测试与基线,并报告任何差异。
./CIME/Tools/compare_test_results -b master SMS.ne30_f19_g16_rx1.A
10.7.4. 性能基线
默认情况下,性能基线是通过解析耦合器日志并比较每日模拟年数(SYPD)中的吞吐量和内存使用峰值生成的。
这可以通过在 $DRIVER_ROOT/cime_config/customize
下创建一个 Python 模块来自定义。有四个钩子可用于自定义生成和比较。
-
perf_get_throughput
-
perf_get_memory
-
perf_compare_throughput_baseline
-
perf_compare_memory_baseline
以下伪代码是这种自定义的示例。
# $DRIVER/cime_config/customize/perf_baseline.py
def perf_get_throughput(case):
"""
Parameters
----------
case : CIME.case.case.Case
Current case object.
Returns
-------
str
Storing throughput value.
str
Open baseline file for writing.
"""
current = analyze_throughput(...)
return json.dumps(current), "w"
def perf_get_memory(case):
"""
Parameters
----------
case : CIME.case.case.Case
Current case object.
Returns
-------
str
Storing memory value.
str
Open baseline file for writing.
"""
current = analyze_memory(case)
return json.dumps(current), "w"
def perf_compare_throughput_baseline(case, baseline, tolerance):
"""
Parameters
----------
case : CIME.case.case.Case
Current case object.
baseline : str
Baseline throughput value.
tolerance : float
Allowed difference tolerance.
Returns
-------
bool
Whether throughput diff is below tolerance.
str
Comments about the results.
"""
current = analyze_throughput(case)
baseline = json.loads(baseline)
diff, comments = generate_diff(...)
return diff, comments
def perf_compare_memory_baseline(case, baseline, tolerance):
"""
Parameters
----------
case : CIME.case.case.Case
Current case object.
baseline : str
Baseline memory value.
tolerance : float
Allowed difference tolerance.
Returns
-------
bool
Whether memory diff is below tolerance.
str
Comments about the results.
"""
current = analyze_memory(case)
baseline = json.loads(baseline)
diff, comments = generate_diff(...)
return diff, comments