Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/322.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_Python 3.4 - Fatal编程技术网

Python 为什么多线程和单线程之间没有执行时间差异

Python 为什么多线程和单线程之间没有执行时间差异,python,multithreading,python-3.4,Python,Multithreading,Python 3.4,我正在努力学习python语言及其概念。我写了一些代码来处理多线程。但我注意到多线程和单线程之间没有执行时间差 运行脚本的机器有4个核心/线程 def get_tokens(file_name,map): print(file_name) counter = 0 with open(file_name,'r',encoding='utf-8-sig') as f: for line in f: item = json.loads(

我正在努力学习python语言及其概念。我写了一些代码来处理多线程。但我注意到多线程和单线程之间没有执行时间差

运行脚本的机器有4个核心/线程

 def get_tokens(file_name,map):
    print(file_name)
    counter = 0
    with open(file_name,'r',encoding='utf-8-sig') as f:
        for line in f:
            item = json.loads(line,encoding='utf-8')
            if 'spot' in item and item['sid'] == 4663:
                counter+=1
                if counter == 500:
                    break
                tokens = nltk.word_tokenize(item['spot'],language='english')
                for token in tokens:
                    if token not in map:
                        map[token] = 1
                    else:
                        map[token] = map[token] + 1;

 start_time = time.time()
 map = dict();
 with ThreadPoolExecutor(max_workers=3) as executor:
    for file in FileProcessing.get_files_in_directory('D:\\Raw Data'):
        future = executor.submit(FileProcessing.get_tokens, file, map)

 end_time = time.time()
 print("Elapsed time was %g seconds" % (end_time - start_time))

原始数据中每个文件的大小都大于25 mb。所以我想他们之间一定有区别。但事实并非如此。为什么?我是否在代码或多线程概念上犯了错误?

问题在于,是否可以通过线程来改进代码。如果代码是串行的,并且一件事情在直线上一件接一件地发生,那么无论有多少线程,代码都将运行相同的代码。但是,如果代码可以分支并同时执行操作a和操作b,那么它将执行。仔细看你的代码,似乎没有分支,至少我知道没有

Python具有防止同一Python进程中的两个执行线程同时执行的功能。因此,虽然python线程在单个进程中为您提供了多个控制路径,但这些多个控制路径不能在多核机器上同时执行。另一种方法是使用python,它将实际创建单独的进程,然后让这些进程通过进程间通信(IPC)进行通信。您还可以尝试使用,它将生成多个进程,因此您不会遇到GIL(Python的标准实现)的问题。CPython不支持不同CPU上的多线程。因此,您确实可以有多个线程,但它们都将在同一个CPU上运行,并且对于CPU绑定的进程(对于I/O绑定的进程)不会有速度改进

原因是臭名昭著的GIL(全局解释器锁)。Python的核心不是线程安全的,因为它执行垃圾收集的方式,所以它使用锁,这意味着访问Python对象的线程会一个接一个地运行

在您的特定情况下,您正在执行一些I/O和一些处理。在python中进行多处理时会有很大的开销,而I/O速度的提高并不能弥补这一开销(与处理文件的时间相比,读取文件的时间可能很短)


如果您需要执行真正的多线程处理,请查看Cython(不要与CPython混淆)和“no_gil”,或c扩展,或多处理模块。

您的代码受CPU限制-默认情况下,多线程将保留在单个CPU内。您可以使用,它允许您创建子流程并基本上绕过GIL(全局解释器锁)。当然,只有当您有多个CPU时,这才有帮助。我不认为这个用例需要多个进程的开销。

GIL的评论是正确的,但是这个代码更可能是IO绑定的,而不是CPU绑定的

即使您使用C或Java之类的工具,您仍然在通过串行接口读取文件,因此除非您无法处理100-300 MB/s的JSON,否则您将看不到线程带来的性能好处

@DevShark说您会看到IO绑定进程的好处,但它比这更复杂。对于高延迟的并发网络连接,这往往更为重要。在这种情况下,您将在磁盘上绑定IO,而不是在进程上(您没有等待远程响应),因此并行性没有帮助


如果您是CPU受限的,有真正的线程,并且正在使用旋转磁盘,那么仍然需要仔细调整缓冲区大小。10ms的寻道时间可能会使您丧命,因此如果您想要高磁盘吞吐量,则需要使用缓冲区大小远大于此值的缓冲读取。对于一个100MB/s、搜索时间为10ms的磁盘,我会使用10MB的缓冲区,但这仍然意味着您要在磁盘上花费10%的搜索时间。我也会协调我的阅读,这样一次只有一个读者阅读。

executor.submit()
似乎是在试图安排并发工作。谢谢大家。没问题,很乐意帮忙:)我读了一些关于python文档上的多处理包的内容。他们说“多处理包提供本地和远程并发,通过使用子进程而不是线程,有效地避开了全局解释器锁。”然后我测试了它,主进程创建的进程不能同时工作。它们比线程更有效,但不是同时有效。