Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python3 asyncio和GIL(如何使用所有cpu核-ProcessPoolExecutor之外的任何其他选项)?_Python_Python 3.x_Python Multiprocessing_Python Asyncio - Fatal编程技术网

Python3 asyncio和GIL(如何使用所有cpu核-ProcessPoolExecutor之外的任何其他选项)?

Python3 asyncio和GIL(如何使用所有cpu核-ProcessPoolExecutor之外的任何其他选项)?,python,python-3.x,python-multiprocessing,python-asyncio,Python,Python 3.x,Python Multiprocessing,Python Asyncio,如何使用所有cpu核进行异步IO-ProcessPoolExecutor之外的任何其他选项 我假设asyncio不能突破GIL限制,也许我错了,所以程序的执行速度会比普通版本快,但只能在一个内核上执行 我研究了一些示例,发现其中一种方法是多处理和ProcessPoolExecutor 这很好,但需要在进程之间进行pickle,因此需要一些开销,并对传递的参数进行一些优化,以减少pickle序列化 使用上面这个简单的模式,我编写了这样的测试代码,如果您不喜欢它,您可以跳过代码阅读,因为它和以前一样

如何使用所有cpu核进行异步IO-ProcessPoolExecutor之外的任何其他选项

我假设asyncio不能突破GIL限制,也许我错了,所以程序的执行速度会比普通版本快,但只能在一个内核上执行

我研究了一些示例,发现其中一种方法是多处理和ProcessPoolExecutor

这很好,但需要在进程之间进行pickle,因此需要一些开销,并对传递的参数进行一些优化,以减少pickle序列化

使用上面这个简单的模式,我编写了这样的测试代码,如果您不喜欢它,您可以跳过代码阅读,因为它和以前一样。顺便说一句,这是解决我解析文件问题的最快方法。这部分代码不是整个程序

def _match_general_and_specific_file_chunk(file_name):
    with codecs.open(file_name, encoding='utf8') as f:
        while True:
            lines = f.readlines(sizehint=10000)
            if not lines:
                break
            for line in lines:
                general_match = RE_RULES.match(line)
                if general_match:
                    specific_match = RULES[general_match.lastindex].match(line)
                    groups = list(specific_match.groups())
                    continue


async def _async_process_executor_match_general_and_specific_read_lines_with_limit_file_chunk():
    loop = asyncio.get_event_loop()
    with ProcessPoolExecutor() as pool:
        futures = []
        for file_name in get_file_names():
            future = loop.run_in_executor(pool, _match_general_and_specific_file_chunk, file_name)
            futures.append(future)
        await asyncio.gather(*futures)


def async_process_executor_match_general_and_specific_read_lines_with_limit_file_chunk():
    asyncio.run(_async_process_executor_match_general_and_specific_read_lines_with_limit_file_chunk())
如何使用所有cpu核进行异步IO-ProcessPoolExecutor之外的任何其他选项

Asyncio对于该作业来说是错误的工具,因为它是专门为管理IO绑定程序的状态而设计的,您可以将其视为Twisted的后续工具

要并行执行CPU绑定的代码,需要线程或进程提供操作系统级并发。在Python中,最方便的方法是concurrent.futures模块,类首先喜欢并来自该模块。您只需要将工作的一部分交给执行人,并完成由此产生的未来

如果要避免酸洗的开销,有两种方法:

使用进程,并利用共享内存、映射内存或管理器对象在控制进程和工作进程之间建立联系

使用线程,但在执行CPU密集型工作时调用内部释放GIL的代码。有些软件包已经这样做了,例如,或,但如果您有这些软件包未涵盖的需求,则这对您没有帮助。在这种情况下,您可能需要编写一个新的C扩展,有关如何临时释放GIL以及何时安全释放GIL的详细信息,请参阅


是的,异步IO只会帮助并行IO操作。lines/regex循环仍然大部分是纯Python的,因此它不会在同一进程内并行化。OP的代码也可能会从多进程的分叉中受益,因为RE_规则和规则看起来像全局常量,当它们分叉时会直接映射到子进程中。@AKX希望即使在繁殖模式下也会出现加速,因为像规则这样的全局变量只会生成一次,并且进程被池重用。OP案例中的问题可能是匹配操作是轻量级的,因此对工作进程执行pickle和unpickle请求可能比只执行工作更昂贵。优化这些场景需要很多耐心,并尝试不同的方法,例如批处理行,或手工编码与工作人员的专门通信。当然,即使是生成模式也会有所帮助,但每个进程都必须自己构建/加载对象。@AKX是的,但每个工作人员只能构建/加载一次。与每个工作进程在其生命周期内处理的项目数量相比,这应该可以忽略不计。与工作进程输入和输出的数量相比,全局进程的初始化不是问题。我认为从实践的角度来看,通过规则、重新规则会过度优化。我将首先关注worker的I/o,因为它将有1/6行需要解析,其中1/100行是结果。
def _match_general_and_specific_file_chunk(file_name):
    with codecs.open(file_name, encoding='utf8') as f:
        while True:
            lines = f.readlines(sizehint=10000)
            if not lines:
                break
            for line in lines:
                general_match = RE_RULES.match(line)
                if general_match:
                    specific_match = RULES[general_match.lastindex].match(line)
                    groups = list(specific_match.groups())
                    continue


async def _async_process_executor_match_general_and_specific_read_lines_with_limit_file_chunk():
    loop = asyncio.get_event_loop()
    with ProcessPoolExecutor() as pool:
        futures = []
        for file_name in get_file_names():
            future = loop.run_in_executor(pool, _match_general_and_specific_file_chunk, file_name)
            futures.append(future)
        await asyncio.gather(*futures)


def async_process_executor_match_general_and_specific_read_lines_with_limit_file_chunk():
    asyncio.run(_async_process_executor_match_general_and_specific_read_lines_with_limit_file_chunk())