python 程序优化/并行? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
billgreen1
V2EX    Python

python 程序优化/并行?

  •  
  •   billgreen1 2016-03-22 07:23:46 +08:00 4325 次点击
    这是一个创建于 3558 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我现在要将股票的 tick 数据转成频率为 1 分钟的数据。 数据是存在 amazon s3, 一个日期(文件夹)下面有 2400+只股票,以 zip 格式存储, zip 里面是 一个 csv 文件。 一个 csv 文件大约在 4000+行。

    可以认为 csv 文件就是有一列是时间,大约间隔 3 秒,从 9:25:xx-15:0x:xx ,一列是价格。

    现在采用的是笨办法,把文件下载到本地,已经下载了一个月的,大约 2G 左右。

    主要写了 2 个函数,一个是读 zip 文件到 pandas 的 dataframe ,另一个是转换 dataframe 至 1min 的频率(这里是使用 dataframe 的 resample 函数)。

    为了使用 resample , dataframe 的 index 需要是 DatetimeIndex 格式。 我尝试了几种方法。

    1. 使用 Pandas 的 DatetimeIndex ,很耗时。
    2. strptime 也是很耗时。
    3. 使用 datetime.datetime , 类似如下调用:
    def parse(time_string): year = int(time_string[0:4]) mOnth= ... ... dt = datetime.datetime(year,month,...) return dt 

    方法 3 比方法 1 、 2 快 3-30 倍左右。但是即使这样,还是很耗时。

    def zip_to_dataframe(zipped_file): ... # index 之前是字符串格式 df.index = df.index.map(parse) # 本行耗时占整个函数的 60% ... 

    第二个函数

    def transform_dataframe(df): ... col_loc = transformed_df.columns.get_loc('open') #取得开盘价所在的列位置 transformed_df.iloc[0,col_loc] = open_price # 本行耗时占整个函数的 45% ... 

    对于处理一个 zip 文件,两个函数各自耗时 100+毫秒左右。如果按照两个函数耗时 0.25 秒算, 0.25(秒) * 2400(一天有 2400 左右只股票) * 20(一个月大概 20 个左右的交易日) * 12(个月) / 3600(秒) = 40 小时!

    即使我用并行,公司电脑只有双核.也要 20 小时。这只是 1 年的,如果要转换多年的。。。

    我现在想到的:

    1. 优化程序,减少耗时。对我来说很难想的出来了, datetime.datetime 后面应该是用的 C 函数吧?感觉很难提升了。 我想不明白为什么对一个单元格赋值会占用那么大的时间。

    2. 把程序拷到其他电脑,一台电脑跑一年的数据,感觉这办法太土。。。。

    3. 用 spark 分布式?没处理过,公司没用 spark ,我都是单机版玩玩,如果这是正途,我愿意试试。

    4. 请多多赐教

    17 条回复    2016-03-22 14:56:08 +08:00
    casparchen
        1
    casparchen  
       2016-03-22 07:32:34 +08:00 via iPad
    去找找有没有一分钟的数据呢
    loggerhead
        2
    loggerhead  
       2016-03-22 08:23:45 +08:00 via iPhone
    没仔细看,想到两个办法:
    1. 换种语言实现,或者用 pypy
    2. 起多个进程分别对不同的 zip 操作
    clino
        3
    clino  
       2016-03-22 08:39:24 +08:00 via Android
    现在笔记本都有八核了。。。
    elitezhe
        4
    elitezhe  
       2016-03-22 09:08:30 +08:00
    两核不代表只能开两个线程啊,网络通信更多时间应该是花在了等待上,所以还是可以多开几个线程的啊
    bigtan
        5
    bigtan  
       2016-03-22 09:11:19 +08:00
    我天天做这个,颇有心得,速度有办法提高数倍,可以联系我。
    mhycy
        6
    mhycy  
       2016-03-22 09:15:07 +08:00
    方便放个样本和示例么?
    clino
        7
    clino  
       2016-03-22 09:22:50 +08:00
    transformed_df 是什么对象? 它是最终你要的结果吗?
    evilic
        8
    evilic  
       2016-03-22 09:25:22 +08:00
    mark
    lecher
        9
    lecher  
       2016-03-22 09:31:36 +08:00 via Android
    Parse 可以优化,因为是连续时间,没必要每个数据序列都从字符串切割年月日这类的,改成预生成,取起始和结束两个时间段,直接把时间段字典构造好。
    或者改成 singleton 模式,年月日时这类的直接缓存在类变量里面,有缓存的话就不要切割这段字符串了,直接取分秒的切割。
    我倾向于第一种。

    读 zip 文件和解包是磁盘 IO 和 CPU 密集型的活问,用 Python 估计优化提升的空间不大,要加速可能把用 SSD 或者把所有文件都读到内存再处理比较好。
    likuku
        10
    likuku  
       2016-03-22 09:40:39 +08:00
    python 嘛,一个 python 进程也只能用到 1 个 CPU 核,线程也只是一个进程内的。

    我之前这么玩:
    python 使用任务队列 queue ,根据可用的 cpu 核数量,开对应数量的 线程,
    线程去 任务队列领任务,开子进程 subprocess 来处理任务。

    如此这般,可以同时利用多个核。

    虽然丑了点。

    这么作有条件的:
    任务可以互不关联的独立处理,没有依赖性。

    或者,自己在外部解决进程间通讯(简易方法,可以用本地文件 /db/memcache/nosql 提供多进程读写状态)
    gamexg
        11
    gamexg  
       2016-03-22 09:41:30 +08:00
    没细看,记得以前看过一篇说 python date 慢的文章,应该有用

    strptime 真慢……
    https://onebitbug.me/2013/09/27/python-strptime-is-super-slow/
    clino
        12
    clino  
       2016-03-22 10:26:56 +08:00
    @likuku 还可以用 uwsgi 来跑多进程,这样比调子进程更好的是已经加载好了更省时间,比如我前两天刚发现的方方式 /t/265065 是用 rpc 来调用,当然也可以变成 http 之类的接口

    不过楼主最多能利用 2 核 所以可能在考虑分布式,不过分布式的问题是不同的机器如何获取到待加工的文件,以及反馈处理过的数据

    用 celery 之类的不知道合不合适
    billgreen1
        13
    billgreen1  
    OP
       2016-03-22 11:12:49 +08:00
    @elitezhe 数据已经被下载到本地了,如果耗时,也应该主要在 IO 上,不在网络通信上
    UnisandK
        14
    UnisandK  
       2016-03-22 11:20:54 +08:00
    https://www.packet.net/bare-metal/


    开台按量的跑完删机器
    pimin
        15
    pimin  
       2016-03-22 11:27:29 +08:00 via Android
    可以丢点数据和 demo 出来给大家练手嘛
    楼主这个问题就实际使用来说,并不是大问题
    一年的数据 20 小时, 10 年也就 200 小时。
    而且是一次性的,处理一次之后以后就没有需求了
    你先找台机器跑起来,过几天就会解决了。
    当然你可能还没把数据都下载完
    如果有好的优化方案你后面处理也不用那么辛苦
    Zzzzzzzzz
        16
    Zzzzzzzzz  
       2016-03-22 12:06:49 +08:00   1
    @likuku pandas 和 Python 的 IO 操作都是释放 GIL, 多线程可以跑在多核上的.
    lebowsk1s
        17
    lebowsk1s  
       2016-03-22 14:56:08 +08:00
    楼主做量化的? anaconda 有个 mkl 发行版,还有个用到 GPU 的发行版,可以一试,还有,你的数据格式不给出来凭空让人看真不好理解
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5204 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 08:39 PVG 16:39 LAX 00:39 JFK 03:39
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86