在很早的时候,就听网上的文章说:
python有GIL,所以在单进程内,即使使用多线程也无法利用到多核的优势,同一时刻,python的字节码只会运行在一个cpu上。
以前也是奉为真理,直到今天在对自己的python server做性能测试的时候,发现一个python进程的cpu居然达到了120%。
当用c++编程的时候,如果使用多线程,那么确实进程cpu超过100%非常正常,但是对python来说,似乎这样就和网上的文章冲突了。
所以还是决定自己亲身试验一下,编写代码如下:
from thread import start_new_thread def worker(): while 1: #print 1 pass for it in range(0, 15): start_new_thread(worker, ()) raw_input()
运行环境为: centos6.4 64位, python 2.7.
得到的结果如下:
可以清楚的看到,pid为31199的python进程cpu达到了787.9%,接近理论能达到的最大值 800%。
而上方的8个cpu也分别达到了近100%的利用率。
如果只是按照以上测试结果,确实可以得出的结论:python使用单进程,多线程确实能够使用到多核cpu,并不是网上传的结论。
但是,还是希望如果有读者对这块有更深入的研究能够进行批评指正,谢谢~
8月15日补充
感谢 la.onger 等几位博友的讨论,现在增加一个测试,用来测试纯cpu计算用一个线程or多个线程完成的总时间的差别,代码如下
import time from threading import Thread LOOPS = 1000000 THREAD_NUM = 10 STEP_SIZE = 94753434 class Test(object): num = 1 def work(self): for it in xrange(0, LOOPS): if self.num > STEP_SIZE: self.num -= STEP_SIZE else: self.num += STEP_SIZE def one_thread_test(self): self.num = 1 begin_time = time.time() for v in xrange(0, THREAD_NUM): self.work() print 'time passed: ', time.time() - begin_time def multi_thread_test(self): self.num = 1 t_list = [] begin_time = time.time() for v in xrange(0, THREAD_NUM): t = Thread(target=self.work) t.start() t_list.append(t) for it in t_list: it.join() print 'time passed: ', time.time() - begin_time t = Test() t.one_thread_test() t.multi_thread_test()
输入结果如下:
time passed: 3.44264101982
time passed: 7.22910785675
使用多线程后,比不用多线程还慢
为了与c++版做对比,也开发了c++代码如下:
#include <stdio.h> #include <string.h> #include <stdint.h> #include <iostream> #include <memory> #include <sstream> #include <algorithm> #include <string> #include <vector> #include <set> #include <map> #include <sys/time.h> #include <pthread.h> using namespace std; #define LOOPS 1000000 #define THREAD_NUM 10 #define STEP_SIZE 94753434 class Test { public: Test() {} virtual ~Test() {} void one_thread_test() { this->num = 1; gettimeofday(&m_tpstart,NULL); for (size_t i = 0; i < THREAD_NUM; ++i) { work(); } gettimeofday(&m_tpend,NULL); long long timeuse=1000000*(long long)(m_tpend.tv_sec-m_tpstart.tv_sec)+m_tpend.tv_usec-m_tpstart.tv_usec;//微秒 printf("time passed: %fn", ((double)timeuse) / 1000000); } void multi_thread_test() { this->num = 1; int ret; vector<pthread_t> vecThreadId;//所有thread的id pthread_attr_t attr; pthread_attr_init (&attr); pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); gettimeofday(&m_tpstart,NULL); pthread_t threadId; for (int i = 0; i < THREAD_NUM; i++) { ret= pthread_create(&threadId, &attr, Test::static_run_work, (void*)this); if(ret!=0){ pthread_attr_destroy (&attr); } vecThreadId.push_back(threadId); } pthread_attr_destroy (&attr); for(vector<pthread_t>::iterator it = vecThreadId.begin(); it != vecThreadId.end(); ++it) { pthread_join(*it, NULL); } gettimeofday(&m_tpend,NULL); long long timeuse=1000000*(long long)(m_tpend.tv_sec-m_tpstart.tv_sec)+m_tpend.tv_usec-m_tpstart.tv_usec;//微秒 printf("time passed: %fn", ((double)timeuse) / 1000000); } void work() { for (size_t i = 0; i < LOOPS; ++i) { if (this->num > STEP_SIZE) { this->num -= STEP_SIZE; } else { this->num += STEP_SIZE; } } } static void* static_run_work(void *args) { Test* t = (Test*) args; t->work(); return NULL; } public: int64_t num; struct timeval m_tpstart,m_tpend; }; int main(int argc, char **argv) { Test test; test.one_thread_test(); test.multi_thread_test(); return 0; }
输出结果如下:
time passed: 0.036114
time passed: 0.000513
可见,c++版确实性能提高了非常多。
由此可见,python的多线程编程,在多核cpu利用上确实差一些。
转载请注明:爱开源 » python单进程能否利用多核cpu的测试结论