【问题标题】:What can be slowing down my program when i use multithreading?当我使用多线程时,什么会减慢我的程序?
【发布时间】:2015-03-02 15:43:38
【问题描述】:

我正在编写一个从网站 (eve-central.com) 下载数据的程序。当我发送带有一些参数的 GET 请求时,它返回 xml。问题是我需要发出大约 7080 个这样的请求,因为我不能多次指定 typeid 参数。

def get_data_eve_central(typeids, system, hours, minq=1, thread_count=1):
    import xmltodict, urllib3
    pool = urllib3.HTTPConnectionPool('api.eve-central.com')
    for typeid in typeids:
        r = pool.request('GET', '/api/quicklook', fields={'typeid': typeid, 'usesystem': system, 'sethours': hours, 'setminQ': minq})
        answer = xmltodict.parse(r.data)

当我刚刚连接到网站并发出所有请求时真的很慢所以我决定让它一次使用多个线程(我读到如果进程涉及大量等待(I/O、HTTP 请求),它可以通过多线程加速很多)。我使用多个线程重写了它,但不知何故它并没有更快(实际上有点慢)。这是使用多线程重写的代码:

def get_data_eve_central(all_typeids, system, hours, minq=1, thread_count=1):

    if thread_count > len(all_typeids): raise NameError('TooManyThreads')

    def requester(typeids):
        pool = urllib3.HTTPConnectionPool('api.eve-central.com')
        for typeid in typeids:
            r = pool.request('GET', '/api/quicklook', fields={'typeid': typeid, 'usesystem': system, 'sethours': hours, 'setminQ': minq})
            answer = xmltodict.parse(r.data)['evec_api']['quicklook']
            answers.append(answer)

    def chunkify(items, quantity):
        chunk_len = len(items) // quantity
        rest_count = len(items) % quantity
        chunks = []
        for i in range(quantity):
            chunk = items[:chunk_len]
            items = items[chunk_len:]
            if rest_count and items:
                chunk.append(items.pop(0))
                rest_count -= 1
            chunks.append(chunk)
        return chunks

    t = time.clock()
    threads = []
    answers = []
    for typeids in chunkify(all_typeids, thread_count):
        threads.append(threading.Thread(target=requester, args=[typeids]))
        threads[-1].start()
        threads[-1].join()

    print(time.clock()-t)
    return answers

我所做的是将所有typeids 分成与我想使用的线程数量一样多的块,并为每个块创建一个线程来处理它。问题是:什么可以减慢它的速度? (我为我糟糕的英语道歉)

【问题讨论】:

    标签: python-3.x python-multithreading


    【解决方案1】:

    Python 有Global Interpreter Lock。这可能是你的问题。实际上,Python 无法以真正的并行方式做到这一点。您可能会考虑切换到其他语言或继续使用 Python,但使用基于进程的并行性来解决您的任务。这是一个很好的演示Inside the Python GIL

    【讨论】:

    • 我也这么认为,但我看不到,我的线程在哪里使用类似的资源。他们使用答案列表,是的,但我尝试将其删除,但它同样慢,所以我认为这不是问题。
    • 看看漂亮的演示文稿dabeaz.com/python/GIL.pdf“Python GIL 内部”。在那之后,我相信您会确切地找到 GIL 给您带来麻烦的原因。
    • 我阅读了演示文稿(顺便说一句,这是一个很棒的演示文稿,谢谢),但我仍然无法弄清楚在我的特定情况下有什么问题。花费大部分时间的操作是等待服务器响应,但它是一个 I/O 操作,它(正如我从演示文稿中理解的那样)应该在等待时释放 GIL,它(根据程序运行的时间来判断) ) 不行。
    • 我使用'for'来给线程分配任务,我认为尝试使用队列是个好主意,就像推荐的here
    • 我使用队列重写了我的程序,它确实快了很多。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-27
    • 2015-07-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多