天道酬勤,学无止境

如何获得 Python 多处理池要完成的“工作”量?(How to get the amount of “work” left to be done by a Python multiprocessing Pool?)

问题

到目前为止,每当我需要使用多处理时,我都是通过手动创建“进程池”并与所有子进程共享工作队列来实现的。

例如:

from multiprocessing import Process, Queue


class MyClass:

    def __init__(self, num_processes):
        self._log         = logging.getLogger()
        self.process_list = []
        self.work_queue   = Queue()
        for i in range(num_processes):
            p_name = 'CPU_%02d' % (i+1)
            self._log.info('Initializing process %s', p_name)
            p = Process(target = do_stuff,
                        args   = (self.work_queue, 'arg1'),
                        name   = p_name)

通过这种方式,我可以向队列中添加内容,这些内容将被子进程使用。 然后我可以通过检查Queue.qsize()监控处理的Queue.qsize()

    while True:
        qsize = self.work_queue.qsize()
        if qsize == 0:
            self._log.info('Processing finished')
            break
        else:
            self._log.info('%d simulations still need to be calculated', qsize)

现在我认为 multiprocessing.Pool 可以简化很多这段代码。

我无法找到的是如何监控仍有待完成的“工作”数量。

以下面的例子为例:

from multiprocessing import Pool


class MyClass:

    def __init__(self, num_processes):
        self.process_pool = Pool(num_processes)
        # ...
        result_list = []
        for i in range(1000):            
            result = self.process_pool.apply_async(do_stuff, ('arg1',))
            result_list.append(result)
        # ---> here: how do I monitor the Pool's processing progress?
        # ...?

有任何想法吗?

回答1

使用Manager队列。 这是一个在工作进程之间共享的队列。 如果您使用普通队列,它会被每个工人腌制和取消腌制,因此会被复制,因此每个工人都无法更新队列。

然后,您让您的工作人员向队列添加内容并在工作人员工作时监视队列的状态。 您需要使用map_async执行此操作,因为这可以让您看到整个结果何时准备就绪,从而可以中断监控循环。

例子:

import time
from multiprocessing import Pool, Manager


def play_function(args):
    """Mock function, that takes a single argument consisting
    of (input, queue). Alternately, you could use another function
    as a wrapper.
    """
    i, q = args
    time.sleep(0.1)  # mock work
    q.put(i)
    return i

p = Pool()
m = Manager()
q = m.Queue()

inputs = range(20)
args = [(i, q) for i in inputs]
result = p.map_async(play_function, args)

# monitor loop
while True:
    if result.ready():
        break
    else:
        size = q.qsize()
        print(size)
        time.sleep(0.1)

outputs = result.get()
回答2

我想出了下面的 async_call 解决方案。

简单的玩具脚本示例,但我认为应该广泛适用。

基本上在无限循环中轮询列表生成器中结果对象的就绪值并求和以计算剩余的已调度 Pool 任务的数量。

一旦没有剩余 break 和 join() & close()。

根据需要在循环中添加睡眠。

原理与上述解决方案相同,但没有队列。 如果您还跟踪最初发送池的任务数量,您可以计算完成百分比等...

import multiprocessing
import os
import time
from random import randrange


def worker():
    print os.getpid()

    #simulate work
    time.sleep(randrange(5))

if __name__ == '__main__':

    pool = multiprocessing.Pool(processes=8)
    result_objs = []

    print "Begin dispatching work"

    task_count = 10
    for x in range(task_count):
        result_objs.append(pool.apply_async(func=worker))

    print "Done dispatching work"

    while True:
        incomplete_count = sum(1 for x in result_objs if not x.ready())

        if incomplete_count == 0:
            print "All done"
            break

        print str(incomplete_count) + " Tasks Remaining"
        print str(float(task_count - incomplete_count) / task_count * 100) + "% Complete"
        time.sleep(.25)

    pool.close()
    pool.join()
回答3

我遇到了同样的问题,并为 MapResult 对象提出了一个稍微简单的解决方案(尽管使用内部 MapResult 数据)

pool = Pool(POOL_SIZE)

result = pool.map_async(get_stuff, todo)
while not result.ready():
    remaining = result._number_left * result._chunksize
    sys.stderr.write('\r\033[2KRemaining: %d' % remaining)
    sys.stderr.flush()
    sleep(.1)

print >> sys.stderr, '\r\033[2KRemaining: 0'

请注意,剩余值并不总是准确的,因为块大小通常根据要处理的项目数向上取整。

你可以通过使用pool.map_async(get_stuff, todo, chunksize=1)来规避这个

回答4

从文档中,在我看来,您想要做的是以列表或其他顺序收集您的result ,然后迭代结果列表检查以ready构建您的输出列表。 然后,您可以通过将未处于就绪状态的剩余结果对象数与已调度作业总数进行比较来计算处理状态。 请参阅 http://docs.python.org/2/library/multiprocessing.html#multiprocessing.pool.AsyncResult

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Marco's Java【面试系列篇之 面试官:你了解线程池么?讲讲它的原理呗!】
    前言 或许大家在日常开发中直接使用线程池的场景不会特别多,但是很多开源框架的底层都会使用到它来管理线程,进而降低资源消耗,提高线程的可管理性。因为线程的创建和销毁都是非常耗费系统资源的,如果不妥善的管理线程(例如,我创建了一个线程,但是忘了释放一些资源,那么很可能会造成资源回收不了,同时也带来一些不必要的系统性能损耗),很容易导致系统问题。其实打从一开始接触线程池,我觉得很简单… 因为使用起来没难度,无非就是声明并创建一个线程池对象,加一些七七八八的参数,然后execute或者submit执行就over了。 但是,谈及它的原理,以及底层的实现时,就傻眼了。 文章目录 前言从本质上解释为什么需要线程池线程池的工作原理线程池的组成线程池的是如何工作的为什么线程池要这么设计 手写一个功能完整的线程池线程池主要参数线程池的资源分配线程池的拒绝策略线程池的任务执行线程池的任务获取线程池的关闭 从本质上解释为什么需要线程池 刚才我们提到了使用线程池可以提高线程的可管理性并降低资源消耗,这个回答其实很笼统,应付的了自己,可应付不了面试大佬啊! 因此,若是被谈及线程池的问题时,我们可以先从这上面两方面去分析。 首先我们要知道一点,创建线程使用是直接向系统申请资源的,Java线程的线程栈所占用的内存是在Java堆外的,而不受Java程序控制,之受限于系统资源,默认一个的线程的线程栈大小为1M
  • 如何在Python中显式释放内存?(How can I explicitly free memory in Python?)
    问题 我编写了一个Python程序,该程序作用于大型输入文件,以创建代表三角形的数百万个对象。 该算法是: 读取输入文件处理文件并创建由三角形顶点表示的三角形列表以OFF格式输出顶点:一个顶点列表,后跟一个三角形列表。 三角形由顶点列表中的索引表示 在打印出三角形之前必须先打印出完整的顶点列表的OFF要求意味着在将输出写入文件之前,必须将三角形的列表保留在内存中。 同时,由于列表的大小,我遇到了内存错误。 告诉Python我不再需要某些数据并且可以释放它们的最佳方法是什么? 回答1 根据Python官方文档,您可以使用gc.collect()显式调用垃圾gc.collect()器以释放未引用的内存。 例子: import gc gc.collect() 您应该在使用del标记要丢弃的内容之后执行此操作: del my_array del my_object gc.collect() 回答2 不幸的是(取决于您的Python版本和版本),某些类型的对象使用“自由列表”,这是一种整洁的局部优化,但可能会导致内存碎片,特别是通过使越来越多的“专用”内存仅用于特定类型的对象而引起的因此无法使用“普通基金”。 确保大量但临时使用内存的唯一真正可靠的方法是在完成后将所有资源都返还给系统,这是让使用发生在子进程中,该进程需要大量内存,然后终止。 在这种情况下,操作系统将完成其工作
  • 线程在Python中是如何工作的,以及特定于Python线程的常见陷阱是什么?(How do threads work in Python, and what are common Python-threading specific pitfalls?)
    问题 我一直在努力地思考线程在Python中的工作方式,而且很难找到有关它们如何运行的良好信息。 我可能只是缺少链接之类的东西,但似乎官方文档对该主题的了解不是很全面,而且我也找不到很好的文章。 据我所知,一次只能运行一个线程,活动线程每10条指令左右切换一次? 哪里有很好的解释,或者您可以提供一个解释? 知道在Python中使用线程时遇到的常见问题也将非常高兴。 回答1 是的,由于全局解释器锁定(GIL),一次只能运行一个线程。 以下是一些有关此方面的见解的链接: http://www.artima.com/weblogs/viewpost.jsp?thread=214235 http://smoothspan.wordpress.com/2007/09/14/guido-is-right-to-leave-the-gil-in-python-not-for-multicore-but-for-utility-computing/ 在最后一个链接中有一个有趣的报价: 让我解释一下这一切的含义。 线程在同一虚拟机内运行,因此在同一物理机上运行。 进程可以在同一台物理计算机上运行,​​也可以在另一台物理计算机上运行。 如果您围绕线程构建应用程序,则您无济于事可访问多台计算机。 因此,您可以扩展到一台计算机上的多个内核(随着时间的推移,内核数量会很多),但是要真正达到Web规模
  • BackgroundWorker vs背景线程(BackgroundWorker vs background Thread)
    问题 我对应该在Windows Form应用程序上使用的后台线程实现的选择有一个风格上的问题。 目前,我在具有无限(while(true))循环的表单上有一个BackgroundWorker 。 在此循环中,我使用WaitHandle.WaitAny来保持线程休眠,直到发生感兴趣的事情为止。 我等待的事件句柄之一是“ StopThread ”事件,因此我可以跳出循环。 从我覆盖的Form.Dispose()发出此事件的信号。 我在某处读到BackgroundWorker确实是用于您不想与UI捆绑在一起并具有有限结局的操作-例如下载文件或处理一系列项目。 在这种情况下,“结束”是未知的,只有在关闭窗口时才知道。 因此,为此目的,使用后台线程而不是BackgroundWorker更合适吗? 回答1 根据我对问题的理解,您正在使用BackgroundWorker作为标准线程。 建议将BackgroundWorker用于您不想占用UI线程的事物的原因是,因为它在进行Win Forms开发时会暴露一些不错的事件。 诸如RunWorkerCompleted事件会在线程完成所需操作时发出信号,而ProgressChanged事件将在线程进度上更新GUI。 因此,如果您不使用这些功能,那么对于需要执行的操作使用标准线程不会有任何危害。 回答2 我的一些想法
  • 干货收藏!Python完整代码带你一文看懂抽样
    01 什么时候需要抽样抽样工作在数据获取较少或处理大量数据比较困难的时期非常流行,这主要有以下几方面原因:数据计算资源不足。计算机软硬件的限制是导致抽样产生的基本原因之一,尤其是在数据密集的生物、科学工程等领域,不抽样往往无法对海量数据进行计算。数据采集限制。很多时候抽样从数据采集端便已经开始,例如做社会调查必须采用抽样方法进行研究,因为根本无法对所有人群做调查。时效性要求。抽样带来的是以局部反映全局的思路,如果方法正确,可以以极小的数据计算量来实现对整体数据的统计分析,在时效性上会大大增强。如果存在上述条件限制或有类似强制性要求,那么抽样工作仍然必不可少。但是在当前数据化运营的大背景下,数据计算资源充足、数据采集端可以采集更多的数据并且可以通过多种方式满足时效性的要求,抽样工作是否就没有必要了?其实不是的,即使上述限制条件都满足,还有很多场景依然需要通过抽样方法来解决具体问题。通过抽样来实现快速的概念验证。数据工作中可能会包括创新性或常识性项目,对于这类项目进行快速验证、迭代和交付结论往往是概念验证的关键,通过抽样方法带来的不仅是计算效率的提升,还有前期数据准备、数据预处理、算法实现等各个方面的开发,以及服务器、硬件的配套方案的部署等内容的可行性、简单化和可操作性。通过抽样来解决样本不均衡问题。通过欠抽样、过抽样以及组合/集成的方法解决不均衡的问题,这个过程就用到了抽样方法
  • 干货收藏!Python完整代码带你一文看懂抽样
    01 什么时候需要抽样抽样工作在数据获取较少或处理大量数据比较困难的时期非常流行,这主要有以下几方面原因:数据计算资源不足。计算机软硬件的限制是导致抽样产生的基本原因之一,尤其是在数据密集的生物、科学工程等领域,不抽样往往无法对海量数据进行计算。数据采集限制。很多时候抽样从数据采集端便已经开始,例如做社会调查必须采用抽样方法进行研究,因为根本无法对所有人群做调查。时效性要求。抽样带来的是以局部反映全局的思路,如果方法正确,可以以极小的数据计算量来实现对整体数据的统计分析,在时效性上会大大增强。如果存在上述条件限制或有类似强制性要求,那么抽样工作仍然必不可少。但是在当前数据化运营的大背景下,数据计算资源充足、数据采集端可以采集更多的数据并且可以通过多种方式满足时效性的要求,抽样工作是否就没有必要了?其实不是的,即使上述限制条件都满足,还有很多场景依然需要通过抽样方法来解决具体问题。通过抽样来实现快速的概念验证。数据工作中可能会包括创新性或常识性项目,对于这类项目进行快速验证、迭代和交付结论往往是概念验证的关键,通过抽样方法带来的不仅是计算效率的提升,还有前期数据准备、数据预处理、算法实现等各个方面的开发,以及服务器、硬件的配套方案的部署等内容的可行性、简单化和可操作性。通过抽样来解决样本不均衡问题。通过欠抽样、过抽样以及组合/集成的方法解决不均衡的问题,这个过程就用到了抽样方法
  • Python:os.fork()如何工作?(Python:How os.fork() works?)
    问题 我正在学习python中的多处理。 我尝试了多处理,在阅读了多处理模块的源代码之后,我发现它使用os.fork() ,因此我编写了一些代码来测试os.fork() ,但是我陷入了困境。 我的代码如下: #!/usr/bin/env python # -*- coding: utf-8 -*- import os import time for i in range(2): print '**********%d***********' % i pid = os.fork() print "Pid %d" % pid 我认为每次打印将执行两次,但它们将执行三次。 我不明白这是怎么回事? 我读过这篇文章需要知道fork是如何工作的? 根据本文的说法,它也会被执行两次,所以我很困惑…… 回答1 为了直接回答这个问题, os.fork()通过调用底层OS函数fork() 。 但是您肯定对它的作用感兴趣。 好吧,这创建了另一个过程,该过程将在与此完全相同的地方恢复。 因此,在第一个循环运行中,您将获得一个派生,其后有两个进程,“原始进程”(获得子进程的PID的pid值)和分叉的进程(获得pid值0 )。 。 他们都打印其pid值,并继续进行第二次循环运行,并同时打印它们。 然后它们都分叉,给您留下4个进程,它们全部打印各自的pid值。 其中两个应为0 ,其他两个应为刚创建的子代的PID
  • 在python中使用多线程时如何获得更快的速度(How to get a faster speed when using multi-threading in python)
    问题 现在,我正在研究如何尽快从网站获取数据。 为了获得更快的速度,即时通讯正在考虑使用多线程。 这是我用来测试多线程和简单文章之间差异的代码。 import threading import time import urllib import urllib2 class Post: def __init__(self, website, data, mode): self.website = website self.data = data #mode is either "Simple"(Simple POST) or "Multiple"(Multi-thread POST) self.mode = mode def post(self): #post data req = urllib2.Request(self.website) open_url = urllib2.urlopen(req, self.data) if self.mode == "Multiple": time.sleep(0.001) #read HTMLData HTMLData = open_url.read() print "OK" if __name__ == "__main__": current_post = Post("http://forum.xda-developers.com
  • 锁定未锁定的互斥锁的效率如何? 互斥锁的成本是多少?(How efficient is locking an unlocked mutex? What is the cost of a mutex?)
    问题 在低级语言(C,C ++或任何其他语言)中:我可以选择是使用一堆互斥对象(例如pthread给我的东西还是本机系统库提供的东西)或一个对象的一个​​。 锁定互斥锁的效率如何? 即可能有多少个汇编程序指令,它们需要多少时间(在互斥锁未锁定的情况下)? 互斥锁的成本是多少? 确实有很多互斥体是一个问题吗? 还是可以在代码中抛出与具有int变量一样多的互斥量变量,这并不重要吗? (我不确定不同的硬件之间有多少区别。如果有,我也想了解它们。但是大多数情况下,我对通用硬件很感兴趣。) 关键是,通过使用许多互斥量(每个互斥量仅覆盖对象的一部分)而不是整个对象的单个互斥量,我可以保护很多块。 我想知道我应该走多远。 即我应该尽可能真正地保护任何可能的块,无论这意味着多少复杂和多少互斥量? WebKits博客文章(2016)中有关锁定的问题与此问题非常相关,并解释了自旋锁,自适应锁,futex等之间的区别。 回答1 我可以选择一堆互斥对象或一个对象互斥对象。 如果您有许多线程并且对对象的访问经常发生,那么多个锁将增加并行性。 以可维护性为代价,因为更多的锁定意味着更多的锁定调试。 锁定互斥锁的效率如何? 即有可能有多少个汇编程序指令,它们需要多少时间(在互斥锁未锁定的情况下)? 精确的汇编程序指令是互斥锁的开销最小-内存/缓存一致性保证是主要的开销。 而且不经常使用特定的锁-更好。
  • 如何在Python多处理中利用所有内核(How to utilize all cores with python multiprocessing)
    问题 现在已经花了一个多小时来摆弄Python的multicore函数,试图使用Process和Manager并行化一个相当复杂的图形遍历函数: import networkx as nx import csv import time from operator import itemgetter import os import multiprocessing as mp cutoff = 1 exclusionlist = ["cpd:C00024"] DG = nx.read_gml("KeggComplete.gml", relabel = True) for exclusion in exclusionlist: DG.remove_node(exclusion) #checks if 'memorizedPaths exists, and if not, creates it fn = os.path.join(os.path.dirname(__file__), 'memorizedPaths' + str(cutoff+1)) if not os.path.exists(fn): os.makedirs(fn) manager = mp.Manager() memorizedPaths = manager.dict() filepaths = manager
  • 刚刚,华为正式开源AI框架MindSpore,还带来了业界最快自动网络架构搜索技术
    2020 年 3 月 27 日至 28 日,华为开发者大会受疫情影响选择以线上直播的方式呈现。会上,华为 MindSpore 首席科学家陈雷博士宣布全场景 AI 计算框架 MindSpore 正式开源。全场景 AI 计算框架 MindSpore 正式开源3 月 28 日上午,华为 MindSpore 首席科学家陈雷博士宣布:全场景 AI 计算框架 MindSpore 正式开源!在去年华为举办的昇腾 910 AI 处理器和 MindSpore 计算框架发布会上,华为曾承诺将在 2020 年 Q1 季度开源 MindSpore。今天,华为兑现承诺,MindSpore 正式开源,四月份即可试用,代码将托管在码云上。这标志着华为已完成全栈全场景 AI 解决方案(Portfolio)的构建,也意味着华为将与所有开发者共建 MindSpore 生态。会议现场,陈雷博士介绍,当下学术界 AI 研究持续升温,今年 AI 顶会论文的投稿量达到了近 9000 篇,各种模型算法层出不穷,工业界 AI 应用层出不穷,例如平安城市、智慧医疗等,我们需要模型能做到大、全、多,也就是数据集大、功能完备,适应多场景。兼顾多方诉求,正是华为设计 MindSpore 的意义。MindSpore 为数据科学家及研究人员提供了全新的工具,使理论探索和创新变得更加简单高效。相比 TensorFlow,MindSpore
  • 如何保护Python代码? [关闭](How do I protect Python code? [closed])
    问题 关闭。 此问题不符合堆栈溢出准则。 它当前不接受答案。 想改善这个问题吗? 更新问题,使它成为Stack Overflow的主题。 7个月前关闭。 改善这个问题 我正在用Python开发一款软件,该软件将分发给我的雇主的客户。 我的雇主想通过限时许可文件来限制软件的使用。 如果我们分发.py文件或什至.pyc文件,将很容易(反编译和)删除检查许可证文件的代码。 另一个方面是,我的雇主不希望我们的客户阅读该代码,因为担心该代码可能被盗或至少是“新颖的主意”。 有解决这个问题的好方法吗? 最好使用现成的解决方案。 该软件将在Linux系统上运行(因此,我认为py2exe不会成功)。 回答1 Python是字节码编译的解释语言,很难锁定。 即使您使用py2exe之类的exe打包程序,该可执行文件的布局也是众所周知的,并且Python字节码也已广为人知。 通常在这种情况下,您必须进行权衡。 保护代码真的有多重要? 那里是否有真正的秘密(例如,对银行转账进行对称加密的密钥),或者您只是偏执? 选择一种语言,使您能够最快地开发出最好的产品,并要对您的新颖创意的价值抱有现实的态度。 如果您确定确实需要安全地执行许可证检查,则将其编写为一个小的C扩展,以便可以对许可证检查代码进行额外的难度(但并非不可能!)以进行反向工程,并将大部分代码保留在Python中。 回答2
  • 如何跳转到巨大文本文件中的特定行?(How to jump to a particular line in a huge text file?)
    问题 以下代码是否有替代方法: startFromLine = 141978 # or whatever line I need to jump to urlsfile = open(filename, "rb", 0) linesCounter = 1 for line in urlsfile: if linesCounter > startFromLine: DoSomethingWithThisLine(line) linesCounter += 1 如果我正在处理一个巨大的文本文件(~15MB) ,其行数未知但长度不同,并且需要跳转到特定行时,我应该事先知道哪个编号? 当我知道我至少可以忽略文件的前半部分时,我很难一一处理它们。 寻找更优雅的解决方案(如果有)。 回答1 线缓存: linecache模块允许人们从Python源文件中获取任何行,同时尝试使用缓存在内部进行优化,这是从单个文件读取多行的常见情况。 追溯模块使用它来检索源行,以将其包含在格式化的追溯中... 回答2 由于您不知道换行符在哪里,因此无法至少一次不读入文件就无法跳转。 您可以执行以下操作: # Read in the file once and build a list of line offsets line_offset = [] offset = 0 for line in file: line
  • Python安装TensorFlow 2、tf.keras和深度学习模型的定义
    原文链接:http://tecdat.cn/?p=15826 深度学习的预测建模是现代开发人员需要了解的一项技能。TensorFlow是Google开发和维护的首要的开源深度学习框架。尽管直接使用TensorFlow可能具有挑战性,但现代的tf.keras API使得Keras在TensorFlow项目中的使用简单易用。使用tf.keras,您可以设计,拟合,评估和使用深度学习模型,从而仅用几行代码即可做出预测。它使普通的深度学习任务(如分类和回归预测建模)可供希望完成任务的普通开发人员使用。在本教程中,您将找到使用tf.keras API在TensorFlow中开发深度学习模型的分步指南。完成本教程后,您将知道:Keras和tf.keras之间的区别以及如何安装和确认TensorFlow是否有效。tf.keras模型的5个步骤的生命周期以及如何使用顺序和功能性API。如何使用tf.keras开发MLP,CNN和RNN模型以进行回归,分类和时间序列预测。如何使用tf.keras API的高级功能来检查和诊断模型。如何通过减少过度拟合和加速训练来提高tf.keras模型的性能。这些例子很小。您可以在大约60分钟内完成本教程。 TensorFlow教程概述本教程旨在为您的深度学习项目提供tf.keras的完整介绍。重点是将API用于常见的深度学习模型开发任务
  • Python,并行处理大文本文件(Python, process a large text file in parallel)
    问题 数据文件(SAM 文件)中的样本记录: M01383 0 chr4 66439384 255 31M * 0 0 AAGAGGA GFAFHGD MD:Z:31 NM:i:0 M01382 0 chr1 241995435 255 31M * 0 0 ATCCAAG AFHTTAG MD:Z:31 NM:i:0 ...... 数据文件是逐行的数据文件的大小从 1G - 5G 不等。 我需要逐行遍历数据文件中的记录,从每一行获取一个特定的值(例如第 4 个值,66439384),并将这个值传递给另一个函数进行处理。 然后一些结果计数器将被更新。 基本工作流程是这样的: # global variable, counters will be updated in search function according to the value passed. counter_a = 0 counter_b = 0 counter_c = 0 open textfile: for line in textfile: value = line.split()[3] search_function(value) # this function takes abit long time to process def search_function (value): some
  • NGINX引入线程池 性能提升9倍
    1. 引言正如我们所知,NGINX采用了异步、事件驱动的方法来处理连接。这种处理方式无需(像使用传统架构的服务器一样)为每个请求创建额外的专用进程或者线程,而是在一个工作进程中处理多个连接和请求。为此,NGINX工作在非阻塞的socket模式下,并使用了epoll 和 kqueue这样有效的方法。因为满负载进程的数量很少(通常每核CPU只有一个)而且恒定,所以任务切换只消耗很少的内存,而且不会浪费CPU周期。通过NGINX本身的实例,这种方法的优点已经为众人所知。NGINX可以非常好地处理百万级规模的并发请求。 每个进程都消耗额外的内存,而且每次进程间的切换都会消耗CPU周期并丢弃CPU高速缓存中的数据。但是,异步、事件驱动方法仍然存在问题。或者,我喜欢将这一问题称为“敌兵”,这个敌兵的名字叫阻塞(blocking)。不幸的是,很多第三方模块使用了阻塞调用,然而用户(有时甚至是模块的开发者)并不知道阻塞的缺点。阻塞操作可以毁掉NGINX的性能,我们必须不惜一切代价避免使用阻塞。即使在当前官方的NGINX代码中,依然无法在全部场景中避免使用阻塞,NGINX1.7.11中实现的线程池机制解决了这个问题。我们将在后面讲述这个线程池是什么以及该如何使用。现在,让我们先和我们的“敌兵”进行一次面对面的碰撞。2. 问题首先,为了更好地理解这一问题,我们用几句话说明下NGINX是如何工作的
  • python爬虫多久能学会-不踩坑的Python爬虫:如何在一个月内学会爬取大规模数据...
    原标题:不踩坑的Python爬虫:如何在一个月内学会爬取大规模数据 Python爬虫为什么受欢迎 如果你仔细观察,就不难发现,懂爬虫、学习爬虫的人越来越多,一方面,互联网可以获取的数据越来越多,另一方面,像 Python这样的编程语言提供越来越多的优秀工具,让爬虫变得简单、容易上手。 利用爬虫我们可以获取大量的价值数据,从而获得感性认识中不能得到的信息,比如: 知乎:爬取优质答案,为你筛选出各话题下最优质的内容。 淘宝、京东:抓取商品、评论及销量数据,对各种商品及用户的消费场景进行分析。 安居客、链家:抓取房产买卖及租售信息,分析房价变化趋势、做不同区域的房价分析。 拉勾网、智联:爬取各类职位信息,分析各行业人才需求情况及薪资水平。 雪球网:抓取雪球高回报用户的行为,对股票市场进行分析和预测。 爬虫是入门Python最好的方式,没有之一。Python有很多应用的方向,比如后台开发、web开发、科学计算等等,但爬虫对于初学者而言更友好,原理简单,几行代码就能实现基本的爬虫,学习的过程更加平滑,你能体会更大的成就感。 掌握基本的爬虫后,你再去学习Python数据分析、web开发甚至机器学习,都会更得心应手。因为这个过程中,Python基本语法、库的使用,以及如何查找文档你都非常熟悉了。 对于小白来说,爬虫可能是一件非常复杂、技术门槛很高的事情。比如有人认为学爬虫必须精通 Python
  • python爬虫怎么爬同一个网站的多页数据-不踩坑的Python爬虫:如何在一个月内学会爬取大规模数据...
    原标题:不踩坑的Python爬虫:如何在一个月内学会爬取大规模数据 Python爬虫为什么受欢迎 如果你仔细观察,就不难发现,懂爬虫、学习爬虫的人越来越多,一方面,互联网可以获取的数据越来越多,另一方面,像 Python这样的编程语言提供越来越多的优秀工具,让爬虫变得简单、容易上手。 利用爬虫我们可以获取大量的价值数据,从而获得感性认识中不能得到的信息,比如: 知乎:爬取优质答案,为你筛选出各话题下最优质的内容。 淘宝、京东:抓取商品、评论及销量数据,对各种商品及用户的消费场景进行分析。 安居客、链家:抓取房产买卖及租售信息,分析房价变化趋势、做不同区域的房价分析。 拉勾网、智联:爬取各类职位信息,分析各行业人才需求情况及薪资水平。 雪球网:抓取雪球高回报用户的行为,对股票市场进行分析和预测。 爬虫是入门Python最好的方式,没有之一。Python有很多应用的方向,比如后台开发、web开发、科学计算等等,但爬虫对于初学者而言更友好,原理简单,几行代码就能实现基本的爬虫,学习的过程更加平滑,你能体会更大的成就感。 掌握基本的爬虫后,你再去学习Python数据分析、web开发甚至机器学习,都会更得心应手。因为这个过程中,Python基本语法、库的使用,以及如何查找文档你都非常熟悉了。 对于小白来说,爬虫可能是一件非常复杂、技术门槛很高的事情。比如有人认为学爬虫必须精通 Python
  • 多少线程太多?(How many threads is too many?)
    问题 我正在编写服务器,并且在收到请求时将的每个操作发送到单独的线程中。 我这样做是因为几乎每个请求都会进行数据库查询。 我正在使用线程池库来减少线程的构造/销毁。 我的问题是:这样的I / O线程的最佳切入点是什么? 我知道这只是一个粗略的估计,但是我们正在讨论数百个吗? 几千? 我将如何确定这个临界值? 编辑: 谢谢大家的答复,看来我只是必须对其进行测试才能确定我的线程数上限。 但问题是:我怎么知道我已经达到那个上限了? 我到底应该测量什么? 回答1 有人会说两个线程太多了-我不在那个阵营里:-) 这是我的建议:衡量,不要猜测。 一种建议是使其可配置并将其初始设置为100,然后将您的软件发布并监视发生的情况。 如果您的线程使用量达到3的峰值,那么100太多了。 如果在一天中的大部分时间里保持在100,将其提高到200,然后看看会发生什么。 实际上,您可以让代码本身监视使用情况,并在下次启动时调整配置,但这可能太过分了。 为了澄清和阐述: 我不主张滚动自己的线程池子系统,请务必使用现有的线程池子系统。 但是,由于您询问的是线程的一个好截止点,因此我假设您的线程池实现可以限制创建的最大线程数(这是一件好事)。 我已经编写了线程和数据库连接池代码,它们具有以下功能(我认为这对于性能至关重要): 最少活动线程数。 最大线程数。 关闭一段时间未使用的线程。
  • 编译/链接过程如何工作?(How does the compilation/linking process work?)
    问题 编译和链接过程如何工作? _(注意:这是[Stack Overflow的C ++常见问题解答](https://stackoverflow.com/questions/tagged/c++-faq)的条目。如果您想批评以这种形式提供FAQ的想法,然后[开始所有这一切的meta上的发布](https://meta.stackexchange.com/questions/68647/setting-up-a-faq-for-the-c-tag)将是执行此操作的地方。在[C ++聊天室](https://chat.stackoverflow.com/rooms/10/c-lounge)中可以监视该问题的答案,而FAQ的想法最初是从这里开始的,因此很可能会回答您以供提出此主意的人阅读。)_ 回答1 C ++程序的编译涉及三个步骤: 预处理:预处理需要花费C ++源代码文件,并处理所述#include S, #define S和其它预处理指令。 此步骤的输出是一个没有预处理程序指令的“纯” C ++文件。 编译:编译器获取预处理器的输出并从中生成一个目标文件。 链接:链接器获取编译器生成的目标文件,并生成库或可执行文件。 前处理 预处理程序处理预处理程序指令,例如#include和#define 。 它与C ++的语法无关,这就是为什么必须谨慎使用它的原因。 通过将