• Jingxiao 置顶
    2019-07-02
    思考题答案:
    import multiprocessing
    import time


    def cpu_bound(number):
        return sum(i * i for i in range(number))


    def find_sums(numbers):
        with multiprocessing.Pool() as pool:
            pool.map(cpu_bound, numbers)


    if __name__ == "__main__":
        numbers = [10000000 + x for x in range(20)]

        start_time = time.time()
        find_sums(numbers)
        duration = time.time() - start_time
        print(f"Duration {duration} seconds")
    展开
    
     7
  • helloworld
    2019-06-28
    总结多线程和协程之间的共同点和区别:
    共同点:
    都是并发操作,多线程同一时间点只能有一个线程在执行,协程同一时间点只能有一个任务在执行;
    不同点:
    多线程,是在I/O阻塞时通过切换线程来达到并发的效果,在什么情况下做线程切换是由操作系统来决定的,开发者不用操心,但会造成race condition;
    协程,只有一个线程,在I/O阻塞时通过在线程内切换任务来达到并发的效果,在什么情况下做任务切换是开发者决定的,不会有race condition的情况;
    多线程的线程切换比协程的任务切换开销更大;
    对于开发者而言,多线程并发的代码比协程并发的更容易书写。
    一般情况下协程并发的处理效率比多线程并发更高。
    展开
    
     18
  • transformation
    2019-06-28
    import time
    from concurrent import futures


    def cpu_bound(number):
        return sum(i * i for i in range(number))


    def calculate_sums(numbers):
        for number in numbers:
            print(cpu_bound(number))


    def main():
        start_time = time.perf_counter()
        numbers = [10000000 + x for x in range(20)]
        calculate_sums(numbers)
        end_time = time.perf_counter()
        print('Calculation takes {} seconds'.format(end_time - start_time))


    def main_process():
        start_time = time.perf_counter()
        numbers = [10000000 + x for x in range(20)]
        with futures.ProcessPoolExecutor() as pe:
            result = pe.map(cpu_bound, numbers)
            print(f"result: {list(result)}")
        end_time = time.perf_counter()
        print('multiprocessing Calculation takes {} seconds'.format(end_time - start_time))


    if __name__ == '__main__':
        main()
        main_process()
    ————————
    输出:
    333333283333335000000
    333333383333335000000
    333333483333355000001
    333333583333395000005
    333333683333455000014
    333333783333535000030
    333333883333635000055
    333333983333755000091
    333334083333895000140
    333334183334055000204
    333334283334235000285
    333334383334435000385
    333334483334655000506
    333334583334895000650
    333334683335155000819
    333334783335435001015
    333334883335735001240
    333334983336055001496
    333335083336395001785
    333335183336755002109
    Calculation takes 15.771127400000001 seconds
    result: [333333283333335000000, 333333383333335000000, 333333483333355000001, 333333583333395000005, 333333683333455000014, 333333783333535000030, 333333883333635000055, 333333983333755000091, 333334083333895000140, 333334183334055000204, 333334283334235000285, 333334383334435000385, 333334483334655000506, 333334583334895000650, 333334683335155000819, 333334783335435001015, 333334883335735001240, 333334983336055001496, 333335083336395001785, 333335183336755002109]
    multiprocessing Calculation takes 4.7333084 seconds
    展开
     5
     6
  • 天凉好个秋
    2019-06-28
    如果完成,则将其放到预备状态的列表;
    如果未完成,则继续放在等待状态的列表。
    这里是不是写的有问题?
    PS:想问一下,完成之后为什么还要放队列里?难道不应该从队列里移除吗?
     2
     5
  • hlz-123
    2019-06-28
    1、单进程,老师的原程序,运行时间
         Calculation takes 15.305913339 seconds
    2、CPU并行方式,运行时间:
         Calculation takes 3.457259904 seconds
          def calculate_sums(numbers):
                 with concurrent.futures.ProcessPoolExecutor() as executor:
                 executor.map(cpu_bound,numbers)
    3、多线程,cocurrent.futures,运行时间
          Calculation takes 15.331446270999999 seconds
          def calculate_sums(numbers):
                    with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
                    executor.map(cpu_bound,numbers)
    4、异步方式,asyncio
          Calculation takes 16.019983702999998 seconds
          async def cpu_bound(number):
                print(sum(i * i for i in range(number)))
          async def calculate_sums(numbers):
               tasks=[asyncio.create_task(cpu_bound(number)) for number in numbers]
               await asyncio.gather(*tasks)
    展开
     1
     4
  • Geek_59f23e
    2019-06-28
    import time
    from multiprocessing import Pool


    def square(number):
        return sum(i * i for i in range(number))


    def single_process(numbers):
        res = []
        for number in numbers:
            res.append(square(number))
        return res


    def multi_process(numbers):
        with Pool() as pool:
            res = pool.map(square, numbers)
        return res


    if __name__ == '__main__':
        numbers = [10000000 + x for x in range(20)]
        start1 = time.perf_counter()
        single_process(numbers)
        print('单进程用时:%f 秒' % (time.perf_counter() - start1))
        start2 = time.perf_counter()
        multi_process(numbers)
        print('多进程用时:%f 秒' % (time.perf_counter() - start2))

    ————————
    输出:
    单进程用时:29.382878 秒
    多进程用时:10.354565 秒

    [333333283333335000000, 333333383333335000000, 333333483333355000001, 333333583333395000005, 333333683333455000014, 333333783333535000030, 333333883333635000055, 333333983333755000091, 333334083333895000140, 333334183334055000204, 333334283334235000285, 333334383334435000385, 333334483334655000506, 333334583334895000650, 333334683335155000819, 333334783335435001015, 333334883335735001240, 333334983336055001496, 333335083336395001785, 333335183336755002109]
    展开
    
     2
  • Destroy、
    2019-06-28
    race condition 是什么?
     1
     2
  • 建强
    2019-10-21
    上网查询资料后,初步了解了多进程的一些知识,按照资料中的方法简单改写了一下程序,由于多进程方式时,不知什么原因,cpu_bound函数不能实时输出,所以就把cpu_bound改为返回字符串形式的结果,等所有的数计算完成后,再一并输出结果 ,程序中常规执行和多进程两种方式都有,并作了对比后发现,常规执行用时约23秒,多进程用时约6秒,两者相差4倍,程序如下,不足处请老师指正:
    #多进程演示
    import multiprocessing
    import time

    def cpu_bound(number):
        return 'sum({}^2)={}'.format(number,sum(i * i for i in range(number)))

    def calculate_sums(numbers):
        
        results = []

        print('-'*10+'串行执行开始:'+'-'*10)

        for number in numbers:
            results.append(cpu_bound(number))

        print('-'*10+'串行执行结束,结果如下:'+'-'*10)
        for res in results:
            print(res)

    def multicalculate_sums(numbers):

        #创建有4个进程的进程池
        pool = multiprocessing.Pool(processes=4)

        results = []

        print('-'*10+'多进程执行开始:'+'-'*10)

        #为每一个需要计算的元素创建一个进程
        for number in numbers:
            results.append(pool.apply_async(cpu_bound, (number,)))

        pool.close() #关闭进程池,不能往进程池添加进程
        pool.join() #等待进程池中的所有进程执行完毕

        print('-'*10+'多进程执行结束,结果如下:'+'-'*10)
        for res in results:
            print(res.get())
        
    def main():

        numbers = [10000000 + x for x in range(20)]

        #串行执行方式
        start_time = time.perf_counter()
        calculate_sums(numbers)
        end_time = time.perf_counter()
        print('串行执行用时:Calculation takes {} seconds'.format(end_time - start_time))

        #多进程执行方式
        start_time = time.perf_counter()
        multicalculate_sums(numbers)
        end_time = time.perf_counter()
        print('多进程执行用时:Calculation takes {} seconds'.format(end_time - start_time))
        
    if __name__ == '__main__':
        main()
    展开

    作者回复: 很棒的例子,但是对计算密集型程序,你可以打开任务管理器的性能页,CPU 选择显示逻辑处理器,可以注意到串行执行和并行执行的不同。

    
     1
  • KaitoShy
    2019-07-03
    运行文章中出现的代码时出现‘aiohttp.client_exceptions.ClientConnectorCertificateError’的这个报错,我讲代码第7行更改成‘async with session.get(url, ssl=False) as resp’后运行成功,是否还有其他的解决方案?
     2
     1
  • 唐哥
    2019-07-01
    老师好,对于 Asyncio 来说,它的任务在运行时不会被外部的一些因素打断。不被打断是如何保证的?还有event loop是每次取出一个任务运行,当这个任务运行期间它就是只等待任务结束吗?不干其他事了吗?
    
     1
  • 方向
    2019-06-28
    如果完成,则放到预备状态列表,这句话不理解。这样一来,预备状态列表同时拥有两种形式的任务啊
     1
     1
  • 苹果
    2020-02-03
    #利用多进程实现上述的计算例子
    import time
    from concurrent import futures
    def cpu_bound(number):
        print(sum(i * i for i in range(number)))

    def calculate_sums(numbers):
        with futures.ProcessPoolExecutor() as executor:
            executor.map(cpu_bound,numbers)

    def main():
        start_time = time.perf_counter()
        numbers = [10000000 + x for x in range(20)]
        calculate_sums(numbers)
        end_time = time.perf_counter()
        print('Calculation takes {} seconds'.format(end_time - start_time))
        
    if __name__ == '__main__':
        main()
    展开
    
    
  • 起于累土
    2019-12-26
    import time
    import multiprocessing


    def cpu_bound(number):
        print(sum(i * i for i in range(number)))


    def calculate_sums(numbers):
        pool = multiprocessing.Pool(processes=4)
        for number in numbers:
            pool.apply_async(cpu_bound, (number,))
        pool.close()
        pool.join()

    def main():
        start_time = time.perf_counter()
        numbers = [10000000 + x for x in range(20)]

        calculate_sums(numbers)
        end_time = time.perf_counter()
        print('Calculation takes {} seconds'.format(end_time - start_time))


    if __name__ == '__main__':
        main()
    展开
    
    
  • Lion
    2019-12-23
    思考题:
    import time
    import os
    from multiprocessing import Pool

    def cpu_bound(number):
        return sum(i * i for i in range(number))

    def calculate_sums(numbers):
        with Pool() as p:
            result = p.map(cpu_bound, numbers)
            for one in result:
                print(one)
                            
    def main():
        start_time = time.perf_counter()
        numbers = [10000000 + x for x in range(20)]
        calculate_sums(numbers)
        end_time = time.perf_counter()
        print('Calculation takes {} seconds'.format(end_time - start_time))
        
    if __name__ == '__main__':
        main()
    展开
    
    
  • 长期规划
    2019-12-23
    老师,我说一下对gevent和asyncio的理解,请指正。gevent的特点是如果对socket打patch,那所有使用socket库的地方都被patch了,影响范围是全局性的,优点是一个同步库在使用gevent后就变成异步了,很方便。而asyncio只在你想异步的地方异步,影响范围是局部性的,更可控,但缺点是一个同步库,你无法使用asyncio。这种理解对吗
    
    
  • 卡卡
    2019-12-17
    老师,你好,python有个多进程的库:multiprocessing,可以详细讲解一下么?
    
    
  • 轻风悠扬
    2019-11-23
    你好老师,我在运行文中例子的时候得到一个RuntimeError: Event loop is closed。
    
    
  • Paul Shan
    2019-11-21
    sync是线性前后执行。
    async是穿插执行,之所以要穿插,代码需要的资源不同,有的代码需要CPU,有的代码需要IO(例如网络),穿插以后,同时需要CPU和网络的代码可以同时执行,充分利用硬件。

    具体到关键字 async 是表示函数是异步的,也就是来回穿插的起点(进入预备队列),await是表示调用需要IO,也就是进入等待队列的入口(函数开始调用)和出口(函数调用结束,重新进入预备队列)。
    
    
  • 。
    2019-11-21
    pyhton 3.7.4 在jupyter中 执行 asyncio.run 还是报RuntimeError: asyncio.run() cannot be called from a running event loop, 换成 await 报SyntaxError: 'await' outside async function,这是什么原因
     1
    
  • 段总
    2019-11-18
    网站下载那个代码出现这个问题:Cannot connect to host en.wikipedia.org:443 ssl:default [远程主机强迫关闭了一个现有的连接。] 烦请大家有空看看该怎么解决?谢过大家!
     1
    
我们在线,来聊聊吧