如何使用 Numba 为 Python 中的线程释放 GIL?
How to release the GIL for a thread in Python, using Numba?
我想做一个程序,包含两部分:一是接收数据,二是写入文件。我认为如果我可以使用 2 个线程(可能还有 2 个 cpu 核心)来单独完成工作会更好。我发现了这个:https://numba.pydata.org/numba-doc/dev/user/jit.html#compilation-options,它允许你释放 GIL。我想知道它是否适合我的目的,我是否可以将它用于这种工作。这是我试过的:
import threading
import time
import os
import queue
import numba
import numpy as np
condition = threading.Condition()
q_text = queue.Queue()
#@numba.jit(nopython=True, nogil=True)
def consumer():
t = threading.currentThread()
with condition:
while True:
str_test = q_text.get()
with open('hello.txt', 'a') as f:
f.write(str_test)
condition.wait()
def sender():
with condition:
condition.notifyAll()
def add_q(arr="hi\n"):
q_text.put(arr)
sender()
c1 = threading.Thread(name='c1', target=consumer)
c1.start()
add_q()
在没有 numba
的情况下工作正常,但是当我将它应用到 consumer
时,它给我一个错误:
Exception in thread c1:
Traceback (most recent call last):
File "d:\python36-32\lib\threading.py", line 916, in _bootstrap_inner
self.run()
File "d:\python36-32\lib\threading.py", line 864, in run
self._target(*self._args, **self._kwargs)
File "d:\python36-32\lib\site-packages\numba\dispatcher.py", line 368, in _compile_for_args
raise e
File "d:\python36-32\lib\site-packages\numba\dispatcher.py", line 325, in _compile_for_args
return self.compile(tuple(argtypes))
File "d:\python36-32\lib\site-packages\numba\dispatcher.py", line 653, in compile
cres = self._compiler.compile(args, return_type)
File "d:\python36-32\lib\site-packages\numba\dispatcher.py", line 83, in compile
pipeline_class=self.pipeline_class)
File "d:\python36-32\lib\site-packages\numba\compiler.py", line 873, in compile_extra
return pipeline.compile_extra(func)
File "d:\python36-32\lib\site-packages\numba\compiler.py", line 367, in compile_extra
return self._compile_bytecode()
File "d:\python36-32\lib\site-packages\numba\compiler.py", line 804, in _compile_bytecode
return self._compile_core()
File "d:\python36-32\lib\site-packages\numba\compiler.py", line 791, in _compile_core
res = pm.run(self.status)
File "d:\python36-32\lib\site-packages\numba\compiler.py", line 253, in run
raise patched_exception
File "d:\python36-32\lib\site-packages\numba\compiler.py", line 245, in run
stage()
File "d:\python36-32\lib\site-packages\numba\compiler.py", line 381, in stage_analyze_bytecode
func_ir = translate_stage(self.func_id, self.bc)
File "d:\python36-32\lib\site-packages\numba\compiler.py", line 937, in translate_stage
return interp.interpret(bytecode)
File "d:\python36-32\lib\site-packages\numba\interpreter.py", line 92, in interpret
self.cfa.run()
File "d:\python36-32\lib\site-packages\numba\controlflow.py", line 515, in run
assert not inst.is_jump, inst
AssertionError: Failed at nopython (analyzing bytecode)
SETUP_WITH(arg=60, lineno=17)
如果我从 consumer
中排除 condition(threading.Condion)
没有错误,所以可能是因为 JIT 不解释它?我想知道我是否可以采用 numba
来达到这种目的,以及如何解决这个问题(如果可能的话)。
您不能在 Numba 函数中使用 threading
模块,并且 opening/writing 也不支持文件。当您需要计算性能时,Numba 非常棒,您的示例纯粹是 I/O,这不是 Numba 的用例。
Numba 添加内容的唯一方法是对 str_test
数据应用函数。使用 nogil=True
编译该函数将允许多线程。但是同样,只有当你的函数与 I/O.
相比计算量大时,这才是值得的
您可以研究一个异步解决方案,它更适合 I/O 约束性能。
有关线程提高性能的案例,请参阅 Numba 文档中的示例:
https://numba.pydata.org/numba-doc/dev/user/examples.html#multi-threading
我想做一个程序,包含两部分:一是接收数据,二是写入文件。我认为如果我可以使用 2 个线程(可能还有 2 个 cpu 核心)来单独完成工作会更好。我发现了这个:https://numba.pydata.org/numba-doc/dev/user/jit.html#compilation-options,它允许你释放 GIL。我想知道它是否适合我的目的,我是否可以将它用于这种工作。这是我试过的:
import threading
import time
import os
import queue
import numba
import numpy as np
condition = threading.Condition()
q_text = queue.Queue()
#@numba.jit(nopython=True, nogil=True)
def consumer():
t = threading.currentThread()
with condition:
while True:
str_test = q_text.get()
with open('hello.txt', 'a') as f:
f.write(str_test)
condition.wait()
def sender():
with condition:
condition.notifyAll()
def add_q(arr="hi\n"):
q_text.put(arr)
sender()
c1 = threading.Thread(name='c1', target=consumer)
c1.start()
add_q()
在没有 numba
的情况下工作正常,但是当我将它应用到 consumer
时,它给我一个错误:
Exception in thread c1:
Traceback (most recent call last):
File "d:\python36-32\lib\threading.py", line 916, in _bootstrap_inner
self.run()
File "d:\python36-32\lib\threading.py", line 864, in run
self._target(*self._args, **self._kwargs)
File "d:\python36-32\lib\site-packages\numba\dispatcher.py", line 368, in _compile_for_args
raise e
File "d:\python36-32\lib\site-packages\numba\dispatcher.py", line 325, in _compile_for_args
return self.compile(tuple(argtypes))
File "d:\python36-32\lib\site-packages\numba\dispatcher.py", line 653, in compile
cres = self._compiler.compile(args, return_type)
File "d:\python36-32\lib\site-packages\numba\dispatcher.py", line 83, in compile
pipeline_class=self.pipeline_class)
File "d:\python36-32\lib\site-packages\numba\compiler.py", line 873, in compile_extra
return pipeline.compile_extra(func)
File "d:\python36-32\lib\site-packages\numba\compiler.py", line 367, in compile_extra
return self._compile_bytecode()
File "d:\python36-32\lib\site-packages\numba\compiler.py", line 804, in _compile_bytecode
return self._compile_core()
File "d:\python36-32\lib\site-packages\numba\compiler.py", line 791, in _compile_core
res = pm.run(self.status)
File "d:\python36-32\lib\site-packages\numba\compiler.py", line 253, in run
raise patched_exception
File "d:\python36-32\lib\site-packages\numba\compiler.py", line 245, in run
stage()
File "d:\python36-32\lib\site-packages\numba\compiler.py", line 381, in stage_analyze_bytecode
func_ir = translate_stage(self.func_id, self.bc)
File "d:\python36-32\lib\site-packages\numba\compiler.py", line 937, in translate_stage
return interp.interpret(bytecode)
File "d:\python36-32\lib\site-packages\numba\interpreter.py", line 92, in interpret
self.cfa.run()
File "d:\python36-32\lib\site-packages\numba\controlflow.py", line 515, in run
assert not inst.is_jump, inst
AssertionError: Failed at nopython (analyzing bytecode)
SETUP_WITH(arg=60, lineno=17)
如果我从 consumer
中排除 condition(threading.Condion)
没有错误,所以可能是因为 JIT 不解释它?我想知道我是否可以采用 numba
来达到这种目的,以及如何解决这个问题(如果可能的话)。
您不能在 Numba 函数中使用 threading
模块,并且 opening/writing 也不支持文件。当您需要计算性能时,Numba 非常棒,您的示例纯粹是 I/O,这不是 Numba 的用例。
Numba 添加内容的唯一方法是对 str_test
数据应用函数。使用 nogil=True
编译该函数将允许多线程。但是同样,只有当你的函数与 I/O.
您可以研究一个异步解决方案,它更适合 I/O 约束性能。
有关线程提高性能的案例,请参阅 Numba 文档中的示例: https://numba.pydata.org/numba-doc/dev/user/examples.html#multi-threading