---
title: 调优简介
description: "应用的代码出现精度问题通常是最难定位的，需要充分运用精度分析工具进行定位。此外，建议优先查看是否存在之前出现过的代码差异。"
url: https://www.hikunpeng.com/document/detail/zh/perftuning/precisionopt/kunpengprecision_12_0026.html
sourcePath: /source/zh/perftuning/precisionopt/kunpengprecision_12_0026.html
indexId: 4981e3f34bf391c5d874d463fd697f321a423bba8a4571545d54b901822d35de64
---
# 调优简介

#### 调优思路

应用的代码出现精度问题通常是最难定位的，需要充分运用精度分析工具进行定位。此外，建议优先查看是否存在之前出现过的代码差异。


#### 主要的代码差异点

案例1：WRF-变量超出设定值。


代码中注释表明：“i_cos、i_tau”的取值范围是“1~10”

但当“cosz(i)、cld_alb”的值为“1”时，“i_cos、i_tau”的结果为“11”，超出了其设计的取值范围。此问题已经在WRF-4.1.2的代码中被修复了，这就确保了“i_cos、i_tau”的值不会超过“10”，修改之后的代码如下所示：


案例2：WRF-数组访问越界。

WPS（WRF Processing System） 所使用的地形数据中，共包含33种地形类型。

num_land_cat =33

WRF代码MPTABLE.TBL配置文件中的地形数据为27，相关变量如SLA的数据维度也只有27维。如果访问到27维以后数据，会出现数组访问越界的问题，导致不同编译器下得到的SLA值不同。


针对phys/module_sf_noahmpdrv.F代码的这个问题，建议的修复方法是：新增对IVGTYP的取值判断，如果其值为31、32、33时，将SLA的下标调整为ISURBAL_TABLE，也即13。修改之后的代码如下所示：


案例3：WRF-进程数不同，计算结果不同。

module_radiation_driver.F里的SUBROUTINE toposhad_init，其代码如下图所示，“ ht_loc”的取值与its、ite、jts、jte的范围有关（每个线程/tile所分配到的区域范围）。当进程数不同时，每个进程所分配到的区域范围不同（进程数多时，每个进程分配到的区域范围小；进程数少时，每个进程分配到的区域范围大），从而会导致“ht_loc”的取值在进程数不同时有差异。从该SUBROUTINE后续的计算可以看到：“ht_loc”的取值影响到shadowmask的结果。当shadowmask不同时，module_surface_driver.F里的SUBROUTINE TOPO_RAD_ADJ的shadow取值可能不同（0或1），这会导致SWDOWN_teradj的结果出现差异，进而导致SUBROUTINE TOPO_RAD_ADJ_DRVR中SWDOWN、GSW、SWNORM的计算结果出现差异。


案例4：GRAPES-数组随机初始化行为差异。

KUO一维整型数组未初始化，直接传入SHALCV函数进行计算。程序默认KUO数组会初始化为0，如果为0会进入物理过程计算逻辑，而实际上在x86计算时KUO数组初始化为随机值，导致程序少了许多物理过程计算，但是阴差阳错结果与实测值更加接近。鲲鹏上的数组有一半正确初始化为0，一半随机数，计算逻辑50%正确，但是结果和实测有偏差。


修改方式如下，只要将未初始化的KUO初始化为非0值，就可以和x86的结果保持高度一致了。


案例5：GRAPES-文件重新读取问题。

在GRAPES算例目录下有“CoLM/odata/ srfdata-g1”文件，计算前如果不将其删除，GRAPES会读取已存在的srfdata-g1文件作为输入，导致结果差异。如果此文件不存在，则会由计算重新生成，计算结束后会保存在“CoLM/odata/ ”目录下。由于这个“CoLM/odata/”目录一般是软连接的，所以存在srfdata-g1文件是重新读取之前的计算结果而不是重新生成的问题。可以在运行算例前加入mv CoLM/odata/srfdata-g1 CoLM/odata/srfdata-g1-old或类似指令去显式删除srfdata-g1文件。

修改方式：计算前删除算例目录下的CoLM/odata/ srfdata-g1
