Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/327.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/0/performance/5.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
Python线程没有提高速度_Python_Multithreading_Cpython_Gil - Fatal编程技术网

Python线程没有提高速度

Python线程没有提高速度,python,multithreading,cpython,gil,Python,Multithreading,Cpython,Gil,为了加速特定的列表处理逻辑,我编写了一个修饰符,它将1)截获传入函数调用2)获取其输入列表,将其分成多个部分4)在单独的线程上将这些部分传递给原始函数5)合并输出和返回 我认为这是一个非常好的主意,直到我编码后,发现速度没有变化!尽管我看到htop上有多个内核在忙,但多线程版本实际上比单线程版本慢 这和臭名昭著的cpython GIL有关系吗 谢谢 from threading import Thread import numpy as np import time # breaks a

为了加速特定的列表处理逻辑,我编写了一个修饰符,它将1)截获传入函数调用2)获取其输入列表,将其分成多个部分4)在单独的线程上将这些部分传递给原始函数5)合并输出和返回

我认为这是一个非常好的主意,直到我编码后,发现速度没有变化!尽管我看到htop上有多个内核在忙,但多线程版本实际上比单线程版本慢

这和臭名昭著的cpython GIL有关系吗

谢谢

from threading import Thread 
import numpy as np 
import time

# breaks a list into n list of lists
def split(a, n):
    k, m = len(a) / n, len(a) % n
    return (a[i * k + min(i, m):(i + 1) * k + min(i + 1, m)] for i in xrange(n))

THREAD_NUM = 8 

def parallel_compute(fn):
    class Worker(Thread):
        def __init__(self, *args):
            Thread.__init__(self)
            self.result = None
            self.args = args
        def run(self):
            self.result = fn(*self.args)
    def new_compute(*args, **kwargs):        
        threads = [Worker(args[0], args[1], args[2], x) for x in split(args[3], THREAD_NUM)]
        for x in threads: x.start()
        for x in threads: x.join()
        final_res = []
        for x in threads: final_res.extend(x.result)
        return final_res        
    return new_compute

# some function that does a lot of computation
def f(x): return np.abs(np.tan(np.cos(np.sqrt(x**2))))

class Foo:
    @parallel_compute
    def compute(self, bla, blah, input_list):
        return map(f, input_list)

inp = [i for i in range(40*1000*100)]
#inp = [1,2,3,4,5,6,7]

if __name__ == "__main__": 

    o = Foo()
    start = time.time()
    res = o.compute(None, None, inp)
    end = time.time()
    print 'parallel', end - start
单线程版本

import time, fast_one, numpy as np

class SlowFoo:
    def compute(self, bla, blah, input_list):
        return map(fast_one.f, input_list)

if __name__ == "__main__": 

    o = SlowFoo()
    start = time.time()
    res = np.array(o.compute(None, None, fast_one.inp))
    end = time.time()
    print 'single', end - start
这是一个多处理版本,它给出了“PicklingError:Can't pickle:attribute lookup\uuuu内置函数失败”。


是的,当线程执行用Python实现的CPU绑定的工作时(比如说,不是通过C扩展实现的,C扩展可以在从Python结构编组/解编组数据之前和之后释放GIL),GIL是一个问题


我建议使用一个多处理模型,一个没有多处理模型的Python实现(IronPython、Jython等),或者使用一种完全不同的语言(如果你做的是性能敏感的工作,那么没有任何语言可以像Python一样流畅,但运行时性能要高得多).

或者,您可以重新设计并启动子流程中的所有并行代码

您需要启动子进程进行计算的工作线程。
这些子流程可以真正并行运行

这是一种重复,请尝试多处理,或者搜索您的答案(有很多答案)。这样的并行处理通常会带来一些开销。您可能需要有一个相当大规模的进程,才能看到相对于单线程版本的实际改进。我已经分别阅读了有关多处理的内容。这有它自己的问题——我的直接问题是Python线程。它在“CPython实现细节:在CPython中,由于全局解释器锁,一次只能有一个线程执行Python代码(即使某些面向性能的库可能会克服此限制)。如果您想让应用程序更好地利用多核计算机的计算资源,建议您使用多处理。但是,如果您想同时运行多个I/O绑定任务,线程仍然是一种合适的模式。“只读共享很简单——您无需执行,你的孩子有你的州的副本。如果没有明确的机制,无法将更改写回父级,但是…这是(先前建议的)多处理模块所做的(使用类似线程的接口)。
import pathos.multiprocessing as mp
import numpy as np, dill
import time

def split(a, n):
    k, m = len(a) / n, len(a) % n
    return (a[i * k + min(i, m):(i + 1) * k + min(i + 1, m)] for i in xrange(n))

def f(x): return np.abs(np.tan(np.cos(np.sqrt(x**2))))

def compute(input_list):
    return map(f, input_list)

D = 2; pool = mp.Pool(D)
def parallel_compute(fn):
    def new_compute(*args, **kwargs):
        inp = []
        for x in split(args[0], D): inp.append(x)
        outputs_async = pool.map_async(fn, inp)
        outputs = outputs_async.get()
        outputs = [y for x in outputs for y in x]
        return outputs
    return new_compute

compute = parallel_compute(compute)

inp = [i for i in range(40*1000)]

if __name__ == "__main__": 

    start = time.time()
    res = compute(inp)
    end = time.time()
    print 'parallel', end - start
    print len(res)