6

背景

我在一家研究风暴潮的研究机构工作,我正在尝试使用 Bash 自动化一些 HPC 命令。目前,该过程是我们从 NOAA 下载数据并逐行手动创建命令文件,输入每个文件的位置以及程序从该文件读取数据的时间和风放大系数。NOAA 生成的每个下载文件中都有数百个这样的数据文件,当暴风雨进行时,这些文件每 6 小时左右出现一次。这意味着我们在风暴期间的大部分时间都花在制作这些命令文件上。

问题

我可以用来自动执行此过程的工具有限,因为我只有一个用户帐户和每月在超级计算机上分配的时间;我无权在它们上安装新软件。另外,其中一些是 Cray,一些是 IBM,一些是 HP,等等。它们之间没有一致的操作系统;唯一的相似之处是它们都是基于 Unix 的。所以我可以使用 Bash、Perl、awk 和 Python 等工具,但不一定有 csh、ksh、zsh、bc 等工具:

$ bc
-bash: bc: command not found

此外,我的首席科学家要求我为他编写的所有代码都在 Bash 中,因为他理解它,而对 Bash 无法执行的事情的外部程序调用最少。例如,它不能做浮点运算,我需要能够添加浮点数。我可以从 Bash 中调用 Perl,但这很慢:

$ time perl -E 'printf("%.2f", 360.00 + 0.25)'
360.25
real    0m0.052s
user    0m0.015s
sys     0m0.015s

1/20 秒似乎并不长,但是当我必须在一个文件中调用 100 次时,这相当于处理一个文件大约需要 5 秒。当我们每 6 小时只制作一个时,这还不错。然而,如果这项工作被抽象为一项更大的任务,我们将 1,000 场合成风暴一次指向大西洋盆地,以研究如果风暴更强或采取不同的路径会发生什么,5 秒很快就会增长到仅仅处理文本文件一个多小时。当您按小时计费时,这会带来问题。

问题

有什么好方法可以加快速度?我目前for在脚本中有这个循环(运行需要 5 秒的循环):

for FORECAST in $DIRNAME; do
    echo $HOURCOUNT"  "$WINDMAG"  "${FORECAST##*/} >> $FILENAME;
    HOURCOUNT=$(echo "$HOURCOUNT $INCREMENT" | awk '{printf "%.2f", $1 + $2}');
done

我知道一次调用 awk 或 Perl 来循环遍历数据文件比为目录中的每个文件调用一次要快一百倍,而且这些语言可以轻松打开文件并写入文件,但问题是我我正在来回获取数据。我已经找到了很多关于这三种语言(awk、Perl、Python)的资源,但是在将它们嵌入到 Bash 脚本中时却找不到那么多。我能做到的最接近的是制作这个 awk 命令的外壳:

awk -v HOURCOUNT="$HOURCOUNT" -v INCREMENT="$INCREMENT" -v WINDMAG="$WINDMAG" -v DIRNAME="$DIRNAME" -v FILENAME="$FILENAME" 'BEGIN{ for (FORECAST in DIRNAME) do
    ...
}'

但我不确定这是正确的语法,如果是,它是否是解决此问题的最佳方法,或者它是否会起作用。几天来,我一直在撞墙,并决定在插上电源之前先上网。

4

3 回答 3

3

只要你有你需要的能力,Bash 是非常有能力的。对于浮点,您基本上有两个选择,或者bc(至少在您显示的框中没有安装[这有点难以置信])或calc. calc-2.12.4.13.tar.bz2

任何一个包都是灵活且功能强大的浮点程序,可以很好地与 bash 集成。由于权力偏爱 bash,我将研究安装bccalc. (工作保障是个好东西)

如果可以说服您的上级允许perlpython,那么任何一个都可以。如果您从未在其中任何一个中进行过编程,那么两者都会有一个学习曲线,pythonperl. 如果你们那里的上级会读bash,那么翻译perl对他们来说会比他们更容易消化python

正如您所解释的那样,这是您给出的情况的选项的公平概述。无论您的选择如何,在任何语言中,您的任务都不应该是那么艰巨。卡住时只需回退一行。

于 2014-07-02T20:09:46.540 回答
1

启动 awk 或其他命令只是为了进行一次添加永远不会有效。Bash 不能处理浮点数,所以你需要改变你的观点。你说你只需要添加浮点数,我收集这些浮点数代表以小时为单位的持续时间。所以改用秒。

for FORECAST in $DIRNAME; do
    printf "%d.%02d  %s  %s\n" >> $FILENAME \
        $((SECONDCOUNT / 3600)) \
        $(((SECONDCOUNT % 3600) * 100 / 3600)) \
        $WINDMAG \
        ${FORECAST##*/}

    SECONDCOUNT=$((SECONDCOUNT + $SECONDS_INCREMENT))
done

(是标准的,比格式化输出printf好得多)echo

编辑:抽象为一个函数并带有一些演示代码:

function format_as_hours {
    local seconds=$1
    local hours=$((seconds / 3600))
    local fraction=$(((seconds % 3600) * 100 / 3600))
    printf '%d.%02d' $hours $fraction
}

# loop for 0 to 2 hours in 5 minute steps
for ((i = 0; i <= 7200; i += 300)); do
    format_as_hours $i
    printf "\n"
done
于 2014-07-02T19:37:19.027 回答
-2

如果所有这些计算机都是 unice,并且它们被期望执行浮点计算,那么它们中的每一个都必须有一些支持 fp 的应用程序可用。所以一个复合复合命令沿着 bc -l some-comp || 的行 直流电补偿 || ... || perl 一些比较

于 2014-07-02T19:32:39.777 回答