V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
deasty
V2EX  ›  问与答

如何提高 awk 的计算速度

  •  
  •   deasty · 2020-06-18 08:55:14 +08:00 via iPhone · 3722 次点击
    这是一个创建于 1651 天前的主题,其中的信息可能已经有所发展或是发生改变。
    有一个 50M 的文本,90 多万行,每行有个数字,用 shell 写个脚本用 awk 取数后经过一个幂运算再输出到新文本,7 个小时过去了,才完成 20 多万行,如何能提高这个效率?
    第 1 条附言  ·  2020-06-18 10:07:36 +08:00
    原始数据
    BJ|986|daxingqu
    GZ|959|tianhequ
    …省略 90 万行
    我的需求结果是把每行的数字乘以 1024 的平方后放在行首,结果如下
    1033895936|BJ|986|daxingqu
    1005584384|GZ|959|tianhequ
    …省略 90 万行
    第 2 条附言  ·  2020-06-18 10:56:38 +08:00
    $./get.sh input.txt output.txt
    $more get.sh
    #!/bin/sh
    m =$(wc -l $1 |awk {'print $1'})
    for ((i = 1;i <=$m;i ++))
    do
    sed -n ${i}p $1 |awk -F "|" {'print $2*1024^2'} |tr "\n" "|">>$2&&sed -n ${i}p $1 >>$2
    done
    第 3 条附言  ·  2020-06-18 11:18:10 +08:00
    哎,解决了,自己犯 2 了……
    26 条回复    2020-06-18 19:13:42 +08:00
    amoia50
        1
    amoia50  
       2020-06-18 08:58:21 +08:00 via iPhone
    python 不香吗[狗头]
    iintothewind
        2
    iintothewind  
       2020-06-18 09:05:47 +08:00
    xargs, parallel 都可以并行处理 可以试试
    rrfeng
        3
    rrfeng  
       2020-06-18 09:07:36 +08:00 via Android
    每行只有一个数字?没别的?
    运算具体是啥?

    你这相当于没说,咋分析
    delectate
        4
    delectate  
       2020-06-18 09:08:00 +08:00
    7 小时大约 25200s,处理 20w 行,一秒 10 行,不够快。
    要么 py+多进程,要么像楼上说的并行处理,或者干脆把文件拆分,然后多个一起跑也行。
    FrankHB
        5
    FrankHB  
       2020-06-18 09:14:10 +08:00
    为什么非要制造瓶颈?这种简单任务你用 C 临时糊个都不用几分钟,省下几个小时不香吗……
    lululau
        6
    lululau  
       2020-06-18 09:15:01 +08:00 via iPhone
    单行命令的文本处理,python 真不香,sed awk perl ruby 不知道香到哪里去了,你也配叫脚本语言
    CEBBCAT
        7
    CEBBCAT  
       2020-06-18 09:25:54 +08:00 via Android
    上次可能是计算 int64 的移位,awk 确实没有 Python 快,我跑起来一会儿 awk 了发现还没跑好,然后再开了一个终端去写 Python,等我写完跑出结果了 awk 还是没有算完。

    楼上这么说有什么依据吗?
    momocraft
        8
    momocraft  
       2020-06-18 09:50:38 +08:00
    "经过一个幂运算" 是 awk 自己的计算吗?
    layorlayor
        9
    layorlayor  
       2020-06-18 09:51:39 +08:00
    把代码贴出来吧。感觉不应该这么慢
    lululau
        10
    lululau  
       2020-06-18 09:52:55 +08:00
    @CEBBCAT 举两个最简单也最常见的例子:

    文本替换:

    sed 's///'
    gawk 'gsub()'
    perl -pe 's///'
    ruby -pe 'gsub!()'

    取一列并做变换:

    gawk '{print $1*2}'
    perl -alne 'print $F[0]*2'
    ruby -ane 'puts $F[0].to_i * 2'

    欢迎楼下用 python 弄一个更简单的写法来打脸

    还忘了说最近看到的一个行列结构文本处理的瑞士军刀 miller
    ylrshui
        11
    ylrshui  
       2020-06-18 10:10:31 +08:00 via iPhone
    估计 excel 都比这快
    thedog
        12
    thedog  
       2020-06-18 10:30:38 +08:00
    awk 不应该那么慢吧,很多时候,这种简单任务,awk 比 python 快的。
    runze
        13
    runze  
       2020-06-18 10:37:07 +08:00
    代码贴出来看看? awk 虽然不算快,但绝不至于慢到这种程度
    TimePPT
        14
    TimePPT  
       2020-06-18 10:41:56 +08:00 via Android
    这么规整的结构,还要做计算。pandas 很香的
    ygtq
        15
    ygtq  
       2020-06-18 10:45:51 +08:00
    show me the code :)
    xlcoder166
        16
    xlcoder166  
       2020-06-18 10:46:57 +08:00
    现有代码不变的思路 - 分治

    1. 拆原文件至 90W / n ( CPU 核心数)个文件
    2. shell 并行处理 拆分的文件
    youngster
        17
    youngster  
       2020-06-18 10:56:11 +08:00
    估计不是 awk 慢,是你运算太慢,换个换个运算快的语言应该都能解决
    layorlayor
        18
    layorlayor  
       2020-06-18 10:58:48 +08:00
    awk -F'|' '{print $2*1024*1024"|"$0}' 这个很快呀
    layorlayor
        19
    layorlayor  
       2020-06-18 11:03:22 +08:00   ❤️ 1
    awk -F'|' '{print $2*1024*1024"|"$0} input.txt > output.txt
    Vegetable
        20
    Vegetable  
       2020-06-18 11:05:14 +08:00
    你这脚本写的是个啥,处理单行文本还有 for 循环?看着就害怕
    Vegetable
        21
    Vegetable  
       2020-06-18 11:09:39 +08:00
    btw,1024*1024 就是 2**20
    klesh
        22
    klesh  
       2020-06-18 11:22:03 +08:00
    测试命令:
    seq 0 10000 | awk '{print "foo|"$1"|bar"}' > test.txt
    time awk -F'|' '{print $2*1024*1024"|"$0}' test.txt

    结果:
    10484711424|foo|9999|bar
    10485760000|foo|10000|bar

    ________________________________________________________
    Executed in 76.44 millis fish external
    usr time 54.70 millis 0.00 micros 54.70 millis
    sys time 21.51 millis 962.00 micros 20.54 millis


    硬件
    CPU: Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz
    SSD: SanDisk SD8SB8U5
    Kelan
        23
    Kelan  
       2020-06-18 11:57:10 +08:00
    这么小的文本跑 7 个小时有点离谱了把。
    0x11901
        24
    0x11901  
       2020-06-18 16:53:02 +08:00
    说实话每次遇到这种问题总有一群人说用 python 不香么……

    真是应了那句老话:当你手上有一把锤子的时候,看所有的东西都是钉子
    freelancher
        25
    freelancher  
       2020-06-18 18:40:49 +08:00
    结果是个啥。得说呀。还是说附言二就解决了?
    Semidio
        26
    Semidio  
       2020-06-18 19:13:42 +08:00
    @freelancher #24 注意看 18L 和附言 2 的区别
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1058 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 20:09 · PVG 04:09 · LAX 12:09 · JFK 15:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.