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
zckun
V2EX  ›  Python

问个 Python 性能相关的

  •  
  •   zckun · 2020-06-23 14:52:56 +08:00 · 3148 次点击
    这是一个创建于 1374 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有很多个学校,具体就先用一千万吧,每个学校有很多个班级,每个班有很多组男女生(男女成对出现,男女生数量相等)。

    现在要求每个班里的男女生的某个差,比如身高、年龄,只需要知道这里会有点耗时,最后按班级吧结果输出到文件

    要求用 python 实现,对速度有要求

    24 条回复    2020-06-29 01:52:18 +08:00
    wuwukai007
        1
    wuwukai007  
       2020-06-23 15:14:04 +08:00
    pandas
    HashV2
        2
    HashV2  
       2020-06-23 15:15:37 +08:00
    这里性能应该是 sql 相关吧
    Jackeriss
        3
    Jackeriss  
       2020-06-23 15:19:10 +08:00
    这是算法题还是什么?好奇怪的需求
    BBrother
        4
    BBrother  
       2020-06-23 15:31:19 +08:00
    用 numpy 和 numba 来实现,但是我没自己试过
    sss495088732
        5
    sss495088732  
       2020-06-23 15:32:02 +08:00
    from aioelasticsearch import Elasticsearch
    0.0
    Hstar
        6
    Hstar  
       2020-06-23 15:43:57 +08:00
    从题目看, 学校数据毫无意义,反正是按班级 group by
    题干也不是很清晰,实际遇到这种千万~亿级的数据就是直接丢进 es,和 python 毫无关系
    Vegetable
        7
    Vegetable  
       2020-06-23 15:47:34 +08:00
    离开 Python 好球区了。如果你采用循环读一个处理一个的方式的话,效率太低了,可能都没有 SQL 快。
    1000W*10 班级*30*学生,这是 30 亿级别的数据,家用电脑已经无法直接读取到内存里了。如果只是流式处理的话,SQL 查出来的其实就是结果了,python 只负责写文件而已。
    zckun
        8
    zckun  
    OP
       2020-06-23 17:19:03 +08:00
    @Vegetable 我是按每个班级处理的,八个进程,一共有 1500 多个班级,68w 名学生,numpy+pandas 计算用是 93 分钟
    zckun
        9
    zckun  
    OP
       2020-06-23 17:20:13 +08:00
    @Hstar 没办法,人家就是要用 python,而且还要快
    superrichman
        10
    superrichman  
       2020-06-23 17:24:42 +08:00 via iPhone
    @zckun 把代码贴出来,看怎么优化
    helloworld000
        11
    helloworld000  
       2020-06-23 17:31:50 +08:00
    这种都没有 dependence 的就直接上 spark 或者 hadoop 来算要快很多
    Nich0la5
        12
    Nich0la5  
       2020-06-23 18:08:21 +08:00
    这个级别数据用 cython,不过这已经不算 python 了。原生循环有多慢跑个 1e8 就知道了
    Vegetable
        13
    Vegetable  
       2020-06-23 18:18:35 +08:00
    @zckun #8 你这个 68w 学生用时 93 分钟,处理 1w 人需要一分多钟应该是代码有问题了,不应该的,给个 demo 大家才好出主意在代码上优化
    jimrok
        14
    jimrok  
       2020-06-23 18:22:04 +08:00
    zckun
        15
    zckun  
    OP
       2020-06-23 19:21:42 +08:00
    @Vegetable 。。。优化到了 9 分钟,查找部分该用二分的,笨了点
    zckun
        16
    zckun  
    OP
       2020-06-23 19:22:31 +08:00
    @jimrok 谢谢老哥
    BiteTheDust
        17
    BiteTheDust  
       2020-06-23 19:33:29 +08:00
    需要查询的话 预处理好数据然后做 hash 表 然后每次去查表就行了 1e7 的数据应该不会很慢
    其实这个对语言没啥特别的要求
    wangyzj
        18
    wangyzj  
       2020-06-23 19:39:04 +08:00
    pandas 吧
    no1xsyzy
        19
    no1xsyzy  
       2020-06-23 20:28:25 +08:00
    愈发看不懂了,“要求每个班里的男女生的某个差”是笛卡尔积求出差矩阵还是均差?
    为什么会发生二分查找?中间发生了什么?
    lithbitren
        20
    lithbitren  
       2020-06-23 20:43:22 +08:00
    什么鬼,数据才 68 万,遍历一轮数据记录把男女身高总和和个数装进字典,然后遍历字典计算差指输出,最多不超过半秒。
    主楼三十亿个学生是够吓人的,几十分钟是要的。
    lithbitren
        21
    lithbitren  
       2020-06-23 20:50:54 +08:00
    students = [
    ㅤ{
    ㅤㅤ'class': random.randrange(2000),
    ㅤㅤ'sex': random.randint(0, 1),
    ㅤㅤ'height': random.randrange(150, 190)
    ㅤ}
    ㅤfor _ in range(1_000_000)
    ]

    collect = collections.defaultdict(lambda: {
    ㅤ'maleSum': 0,
    ㅤ'maleCount': 0,
    ㅤ'femaleSum': 0,
    ㅤ'femaleCount': 0
    })

    for student in students:
    ㅤif student['sex']:
    ㅤㅤcollect[student['class']]['maleSum'] += student['height']
    ㅤㅤcollect[student['class']]['maleCount'] += 1
    ㅤelse:
    ㅤㅤcollect[student['class']]['femaleSum'] += student['height']
    ㅤㅤcollect[student['class']]['femaleCount'] += 1

    result = [
    ㅤClass['maleSum'] / Class['maleCount'] - Class['femaleSum'] / Class['femaleCount']
    ㅤfor Class in collect.values()
    ]

    测了测,百万级数据查询时间肯定不超过半秒,这还是用带键名的,如果把临时字典换成数组,估计还能再将快几倍,拆分数组类型到 numpy 然后开 numba,估计还能再快几倍,几十分钟居然就真等了。。。
    necomancer
        22
    necomancer  
       2020-06-23 21:07:48 +08:00
    numpy 就可以。anaconda 的 numpy 有 MKL 加速。比如身高,data->(10, 5, 50, 2) 型的数组-> 10 所学校,每个学校 5 个班级,等量男女各 50 人两组身高,只要 np.mean(data, axis=(0,1)) 就是按学校和班级做平均。你还需要什么统计量 numpy 都有现成函数。
    linvaux
        23
    linvaux  
       2020-06-23 23:27:28 +08:00
    @sss495088732 6 的不行
    btv2bt
        24
    btv2bt  
       2020-06-29 01:52:18 +08:00
    pyspark ?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3919 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 05:10 · PVG 13:10 · LAX 22:10 · JFK 01:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.