代码插桩分析法
由于编译器、数学库和硬件上的差异,在鲲鹏平台和x86平台运行结果是不一致的。面对两者的差异,下面的介绍的方法可以准确的找到产生差异的代码,进而分析出原因。
下面以WRF 3.4.1代码进行举例,在分析差异前,需要明确鲲鹏和x86机器上使用的编译器、编译选项和软件栈,保证鲲鹏和x86使用同一WRF版本和同一算例。
图1 插桩分析法流程


插桩思路为:假定在两个平台上函数的输入是一致的,若函数内部的计算不会产生差异,则两个平台上函数输出是一致的。反之,函数内部必然存在产生差异的代码。
找到代码的主要计算路径,如WRF 3.4.1中的solve_em.F,该模块对气象要素进行大量的计算,影响最终的结果生成。对solve_em.F中的所有函数作为目标函数进行插桩分析。
- 满足假定的条件函数输入一致,可通过读写文件操作实现。例如:
- 在x86平台上在调用set_tiles前插入write_args函数,将set_tiles的输入值写入文件。
! x86调用write_args将输入值写入文件 CALL write_args(grid, ids, ide, jds, jde, ips, ipe, jps, jpe) CALL set_tiles(grid, ids, ide, jds, jde, ips, ipe, jps, jpe)
- x86写文件完成后将其拷贝到鲲鹏平台,在鲲鹏平台上同样的代码位置插入函数read_args读取x86上的参数值。
! 鲲鹏调用read_args读取文件值并赋值给输入 CALL read_args(grid, ids, ide, jds, jde, ips, ipe, jps, jpe) CALL set_tiles(grid, ids, ide, jds, jde, ips, ipe, jps, jpe)
- 在x86平台上在调用set_tiles前插入write_args函数,将set_tiles的输入值写入文件。
- 对比两个平台的输出,考虑到函数输出可能是一个极大的数组,直接对比具体的值不直观,可以通过计算输出的md5值进行对比。可在set_tiles后调用print_md5函数进行输出值的md5计算和打印。
- x86平台代码如下:
! x86调用write_args将参数值写入文件 CALL write_args(grid, ids, ide, jds, jde, ips, ipe, jps, jpe) CALL set_tiles(grid, ids, ide, jds, jde, ips, ipe, jps, jpe) ! x86打印输出md5值 CALL print_md5(grid, ids, ide, jds, jde, ips, ipe, jps, jpe)
- 鲲鹏平台代码如下:
! 鲲鹏调用read_args读取文件值并赋值给参数 CALL read_args(grid, ids, ide, jds, jde, ips, ipe, jps, jpe) CALL set_tiles(grid, ids, ide, jds, jde, ips, ipe, jps, jpe) ! 鲲鹏打印输出md5值 CALL print_md5(grid, ids, ide, jds, jde, ips, ipe, jps, jpe)
- x86平台代码如下:
- 对比set_tiles函数输出值md5结果,可以看出两个平台输出是完全一致的,可以断定set_tiles不会导致结果差异。
- 鲲鹏中set_tiles函数输出md5值打印结果:
ids md5sum is :4352d88a78aa39750bf70cd6f27bcaa5 ide md5sum is :78cf7f2f5161bd0bb9fd139e10624c07 jds md5sum is :4352d88a78aa39750bf70cd6f27bcaa5 jde md5sum is :78cf7f2f5161bd0bb9fd139e10624c07 ips md5sum is :4352d88a78aa39750bf70cd6f27bcaa5 ipe md5sum is :b15762fc4c227bbdb97385765fb475f4 jps md5sum is :4352d88a78aa39750bf70cd6f27bcaa5 jpe md5sum is :d2f2de0f320b64a33cdefe91e8632b54
- x86中set_tiles函数输出md5值打印结果:
ids md5sum is :4352d88a78aa39750bf70cd6f27bcaa5 ide md5sum is :78cf7f2f5161bd0bb9fd139e10624c07 jds md5sum is :4352d88a78aa39750bf70cd6f27bcaa5 jde md5sum is :78cf7f2f5161bd0bb9fd139e10624c07 ips md5sum is :4352d88a78aa39750bf70cd6f27bcaa5 ipe md5sum is :b15762fc4c227bbdb97385765fb475f4 jps md5sum is :4352d88a78aa39750bf70cd6f27bcaa5 jpe md5sum is :d2f2de0f320b64a33cdefe91e8632b54
- 鲲鹏中set_tiles函数输出md5值打印结果:
- solve_em.F中还调用calc_p_rho_phi函数,用同样的方法来分析calc_p_rho_phi函数,其输出值md5打印结果:
- 鲲鹏中calc_p_rho_phi函数输出md5值打印结果:
moist md5sum is :6b67192bd614cbcd0e46ed5d607479a0 num_3d_m md5sum is :7303f017fe369f9ce5af630da93ba867 config_flags%hypsometric_opt md5sum is :4352d88a78aa39750bf70cd6f27bcaa5 grid%al md5sum is :db28d22d61ccf7aaef53151c08bad13e grid%alb md5sum is :7df859bac212ad24233f0e35c347b79c grid%mu_2 md5sum is :78da02688276d78aebd7198ffea21ef6 grid%muts md5sum is :dbcaf66d2fb30baafbfab7f075e1325e grid%ph_2 md5sum is :9d5ab368e3398baa8b6eabf310e06515 grid%phb md5sum is :357f65254210d7544455ac35ee9b87b7 grid%p md5sum is :a9d0a0bd98710620b70c8e0b82b8cdf9 grid%pb md5sum is :7b44de932f45be71671722478a4b0c87 grid%t_2 md5sum is :f3d260a80c699900c6294ea356f0d64c p0 md5sum is :a6c5b219b5715388be8ac391f95602ab t0 md5sum is :2b37b3fa8052b64b82a21602e662e4ca grid%p_top md5sum is :96a8a83edaccefc72356a9a64a5484ac grid%znu md5sum is :65337863d0f5ad50c2492ba81f22d7bd grid%znw md5sum is :16b3ab5e2ec5e92d312a055b46ce4cc5 grid%dnw md5sum is :04fdee143ffda95f156e872762efbb17 grid%rdnw md5sum is :f838011b20bb121e63737fde1fd5dd3f grid%rdn md5sum is :a00dba2a5675a1a5ea4b85e97257e1bd config_flags%non_hydrostatic md5sum is :a54f0041a9e15b050f25c463f1db7449
- x86中calc_p_rho_phi函数输出md5值打印结果:
moist md5sum is :6b67192bd614cbcd0e46ed5d607479a0 num_3d_m md5sum is :7303f017fe369f9ce5af630da93ba867 config_flags%hypsometric_opt md5sum is :4352d88a78aa39750bf70cd6f27bcaa5 grid%al md5sum is :db28d22d61ccf7aaef53151c08bad13e grid%alb md5sum is :7df859bac212ad24233f0e35c347b79c grid%mu_2 md5sum is :78da02688276d78aebd7198ffea21ef6 grid%muts md5sum is :dbcaf66d2fb30baafbfab7f075e1325e grid%ph_2 md5sum is :9d5ab368e3398baa8b6eabf310e06515 grid%phb md5sum is :357f65254210d7544455ac35ee9b87b7 grid%p md5sum is :5e0897900e4534f9ad7d70ce616d2954 grid%pb md5sum is :7b44de932f45be71671722478a4b0c87 grid%t_2 md5sum is :f3d260a80c699900c6294ea356f0d64c p0 md5sum is :a6c5b219b5715388be8ac391f95602ab t0 md5sum is :2b37b3fa8052b64b82a21602e662e4ca grid%p_top md5sum is :96a8a83edaccefc72356a9a64a5484ac grid%znu md5sum is :65337863d0f5ad50c2492ba81f22d7bd grid%znw md5sum is :16b3ab5e2ec5e92d312a055b46ce4cc5 grid%dnw md5sum is :04fdee143ffda95f156e872762efbb17 grid%rdnw md5sum is :f838011b20bb121e63737fde1fd5dd3f grid%rdn md5sum is :a00dba2a5675a1a5ea4b85e97257e1bd config_flags%non_hydrostatic md5sum is :a54f0041a9e15b050f25c463f1db7449
- 鲲鹏中calc_p_rho_phi函数输出md5值打印结果:
从两个平台的输出对比可以看出calc_p_rho_phi函数的输出grid%p是不一致的。接下来用同样的插桩思路对calc_p_rho_phi函数中涉及grid%p变量的函数进行插桩分析,最终定位到其调用了vpow函数导致grid%p变量不一致。
图2 vpow代码片段


vpow函数只是做pow运算,跟程序调用的数学库有关。在鲲鹏平台上替换成KML数学库后calc_p_rho_phi函数的输出值与x86保持一致。
遍历所有目标函数,使用插桩方法即可对WRF软件完成结果差异分析。
父主题: 差异分析方法