Python-多线程与并行计算

来源:互联网 发布:黑客盗号软件下载 编辑:程序博客网 时间:2024/05/21 03:58

Python-多线程与并行计算

饿死我了。。。。今天看图像处理cuda的时候看到了并行计算,又恰巧参加第二届CCF举办CCSP比赛的时候,第五题是可以并行计算的。。。在赛后分享上,听清华大佬讲得栩栩如生,我听得一愣一愣的。真的是嘴上笑嘻嘻,心理妈卖批。不过还是比较羡慕他们怎么懂这么多,竞赛也这么强。扯远了,由于C++太繁琐,今天只是浅尝辄止用Python搜集了下资料,顺便跑了下。
科普开始。。。。。Loading
并行计算和多线程的区别
1,很明显并行比多线程具有更高的CPU利用率,因此效率相对更高;
2,并行是利用CPU的多个核进行计算,而多线程是利用CPU一个核在不同时间段内进行计算。
3,并行计算式多个线程运行在多个cpu上, 多线程是多个线程运行在一个cpu上, 并行计算基本是依赖多线程的。
4,多线程是一个线程只能运行在一个CPU,多个线程可以运行在多个CPU;并行计算是一个线程可以运行在多个CPU。
上述讲得很清晰,说白了,并行计算有多个线程和多个进程来实现。其中并行计算可以在多核上运行,多CPU(联机,分布式)上运行。多线程则只能在单个CPU跑,通过信号量,互斥锁来实现并发。做软件的时候,UI设计通常不同按钮要分发给不同的线程。因为你点击这个按钮的时候,窗口资源你在用,如果没有执行完,你立马点击下一个按钮,这就会产生死锁,程序奔溃。所以得分发给不同的线程,让他们同步运行。
进程与线程优缺点  
进程优点:编程、调试简单,可靠性较高。
进程缺点:创建、销毁、切换速度慢,内存、资源占用大。
线程优点:创建、销毁、切换速度快,内存、资源占用小。
线程缺点:编程、调试复杂,可靠性较差。
场景使用  
a.多核CPU——计算密集型任务。此时要尽量使用多进程,可以提高任务执行效率,例如加密解密,数据压缩解压缩(视频、音频、普通数据),否则只能使一个核心满载,而其他核心闲置。
d.多核CPU——IO密集型任务,这就更不用说了,跟单核时候原因一样
同样在这个单核时代,多线程的这个消除阻塞的作用还可以叫做“并发”,这和并行是有着本质的不同的。并发是“伪并行”,看似并行,而实际上还是一个CPU在执行一切事物,只是切换的太快,我们没法察觉罢了。例如基于UI的程序(俗话说就是图形界面),如果你点一个按钮触发的事件需要执行10秒钟,那么这个程序就会假死,因为程序在忙着执行,没空搭理用户的其他操作;而如果你把这个按钮触发的函数赋给一个线程,然后启动线程去执行,那么程序就不会假死,继续相应用户的其他操作。但是,随之而来的就是线程的互斥和同步、死锁等问题
特别:线程必然不是越多越好,线程切换也是要开销的,当你增加一个线程的时候,增加的额外开销要小于该线程能够消除的阻塞时间,这才叫物有所值。
总结
并发:
一、多进程并发
对于计算密集型程序,多进程并发优于多线程并发。密集型程序是运行时间大部分消耗在CPU的运算了。
而硬盘和内存的读写消耗时间很多;相对地,IO密集型程序是指程序运行大部分消耗在硬盘了,CPU的运算时间很短。
1.1采用队列实现-使用multiprocessing.JoinableQueue
1.2进程池实现-使用concurrent.futures.ProcessPoolExecutor
二、多线程并发
对于IO密集型程序多线程并发可能要优于多进程并发。
2.1 队列实现-使用使用queue.Queue
2.2 线程池实现-concurrent.futures.ThreadPoolExecutor
多线程:
http://www.runoob.com/python/python-multithreading.html
实例
多线程求和:
#coding: UTF-8    """ 经过非正规的测试,多线程并行计算并未像想象中那样会比串行计算快。 相反,在我的PC上运行后,多线程并行计算反而慢了。 不知是计算量不够大,还是怎么。(本身内存有限,无法无限加大,在有限测试范围内,结果如上) 过程是:随着计算线程数的增加,计算时间会下降,但到了一定数量(不同机器有所不同)后,计算时间反而增加。 因为很大一部分增加的时间是耗费在线程的创建上的。 """      import threading  import random  import time    class calthread(threading.Thread):      #初始化函数      def __init__(self,threadname,cond,startN,endN):          threading.Thread.__init__(self,name = threadname)          self.cond = cond          self.startN = startN          self.endN = endN          #print "MyName: " + threadname +",start--" +str(startN) +",end--"+str(endN)      #业务函数      def run(self):          global sumN,alist,countFinish          temp = 0          for i in range(self.startN,self.endN + 1):              temp = temp + alist[i]          #累加计算和,并累加完成计数器          self.cond.acquire()          countFinish += 1          sumN += temp          #print "MyName: " + self.getName() +",mySum--" +str(temp) +",countFinish--"+str(countFinish)+",currentTotalSum---"+str(sumN)+"\n"          global threadN          if(countFinish == threadN):              print "End time of threadCal -- " + str(time.time())              print "The total sum : " + str(sumN) + "\n"          self.cond.release()    #获取线程锁  cond = threading.Condition()  #目标计算数组的长度  alen = 10000000  #执行计算工作的线程长度  threadN = 10000  #随机初始化数组元素  alist = []  #alist = [random.uniform(1,1000) for x in range(0,alen)]  for i in range(1,alen+1):      alist.append(i)    #执行线程对象列表  threadL  = []   t = alen/threadN  print "初始化线程"  for x in range(0,threadN):      startN = x*t      endN = 0      if((x+1)*t >= alen):          endN = alen - 1      else:          if(x == threadN - 1):              endN = alen - 1          else:              endN = (x+1)*t - 1      #向列表中存入新线程对象      threadTT = calthread("Thread--"+str(x),cond,startN,endN)      threadL.append(threadTT)    #总计完成线程计数器  countFinish = 0  sumN = 0  print "Start time of threadCal--"+ str(time.time())  for a in threadL:      a.start()    time.sleep(10)  normalSum = 0  print "Start time of normalCal--"+ str(time.time())  for n in range(0,alen):      normalSum += alist[n]  print "End time of normalCal--"+ str(time.time())    print "Normal : " + str(normalSum) + "\n"  
多线程求和:
import threadingfrom math import ceilresult = 0def sub_sum(start, end, step):    global result    sum = float(0)    temp = start    while temp < end + step / 1000000:        sum += temp        temp += step    #print("sum from %f to %f by the step %f is %f"\    #        % (start, end, step, sum))    result += sumdef thread_sum(start, end, step = 1, num_thread = 1):    global result    num_threads = int(num_thread)    if (num_threads <= 0):        num_threads = 1    end = start + int((end - start)/step) * step    numbers = end - start    if (numbers < 0 and step > 0) or (numbers > 0 and step < 0):        print("error in sum: from %f to %f by the step %f is invalid."\                % (start, end, step))        return 0    elif numbers == 0:        return start    if numbers < 0:        (start, end, step) = (end, start, -step)        numbers *= -1    d = ceil(numbers / num_thread / step) * step    if d < step:        d = step    begin = 0    threads = []    while start + begin * d < end:        threads.append(threading.Thread(target=sub_sum,\                args=(start + d * begin,\                    start + d * (begin + 1) - step \                        if start + (begin + 1) * d < end else end,\                    step)))        begin += 1    print("Actual threads count: %d" % len(threads))    for i in range(len(threads)):        threads[i].start()    for i in range(len(threads)):        threads[i].join()    return resultif __name__ == "__main__":    start = raw_input("Please input the start: ")    end = raw_input("Please input the end: ")    step = raw_input("Please input the step(default 1): ")    start = float(start)    end = float(end)    step = 1 if step == "" else float(step)    num_thread = raw_input("Please input the num of threads: ")    num_thread = int(num_thread)    if num_thread < 0:        print("The num_thread must be positive but not %d" % num_thread)        exit(0)    print("Ths sum is: %f" % thread_sum(start, end, step, num_thread))    s = 0    if start < end and step > 0:        while start <= end:            s += start            start += step    elif start > end and step < 0:        while start >= end:            s += start            start += step    print("normal function: %s" % s)
多线程打印1-100
#encoding=utf-8import threadingimport timethreadLock = threading.Lock()num = 0class timer(threading.Thread):    def __init__(self, count, interval):        threading.Thread.__init__(self)        self.interval = interval         self.count = count     def run(self):        global num        while True:            # get lock            threadLock.acquire()            if num >= self.count:                threadLock.release()                break            num += 1            print 'Thread name:%s, %d' % (self.getName(), num)            threadLock.release()                    time.sleep(self.interval)if __name__ == '__main__':    thread1 = timer(1000, 1)     thread2 = timer(1000, 1)     thread1.start()    thread2.start()    thread2.join()    thread2.join()
多进程打印1-100
import multiprocessingdef create_process(tasks):    cpu_count = multiprocessing.cpu_count()    for _ in range(cpu_count):        process = multiprocessing.Process(target=_worker, args=(tasks, ))        process.daemon = True        process.start()        print "process_id-->{}".format(process.pid)def _worker(tasks):    while True:        try:            task = tasks.get()            print "process_id--> {0}, task--> {1}".format(multiprocessing.current_process(), task)        finally:            tasks.task_done()def add_task(tasks, task_count):    for item in range(task_count):        tasks.put(item)def main():    max_num = 10000    tasks = multiprocessing.JoinableQueue()    create_process(tasks)    add_task(tasks, max_num)    tasks.join()if __name__ == '__main__':    main()
并行实例
#-*- coding: UTF-8 -*-import math, sys, timeimport ppdef IsPrime(n):    """返回n是否是素数"""    if not isinstance(n, int):        raise TypeError("argument passed to is_prime is not of 'int' type")    if n < 2:        return False    if n == 2:        return True    max = int(math.ceil(math.sqrt(n)))    i = 2    while i <= max:        if n % i == 0:            return False        i += 1    return Truedef SumPrimes(n):    for i in xrange(15):        sum([x for x in xrange(2,n) if IsPrime(x)])    """计算从2-n之间的所有素数之和"""    return sum([x for x in xrange(2,n) if IsPrime(x)])inputs = (100000, 100100, 100200, 100300, 100400, 100500, 100600, 100700)# start_time = time.time()# for input in inputs:#     print SumPrimes(input)# print '单线程执行,总耗时', time.time() - start_time, 's'# # tuple of all parallel python servers to connect withppservers = ()#ppservers = ("10.0.0.1",)if len(sys.argv) > 1:    ncpus = int(sys.argv[1])    # Creates jobserver with ncpus workers    job_server = pp.Server(ncpus, ppservers=ppservers)else:    # Creates jobserver with automatically detected number of workers    job_server = pp.Server(ppservers=ppservers)print "pp 可以用的工作核心线程数", job_server.get_ncpus(), "workers"start_time = time.time()jobs = [(input, job_server.submit(SumPrimes,(input,), (IsPrime,), ("math",))) for input in inputs]#submit提交任务for input, job in jobs:    print "Sum of primes below", input, "is", job()# job()获取方法执行结果print "多线程下执行耗时: ", time.time() - start_time, "s"job_server.print_stats()#输出执行信息
并行实例
http://blog.csdn.net/dai451954706/article/details/31399317
参考链接
并行:
http://blog.csdn.net/u013378306/article/details/72853750
http://blog.csdn.net/dai451954706/article/details/31399317
多线程:
http://rookiedong.iteye.com/blog/1186004
http://blog.csdn.net/pdcxs007/article/details/49813943
打印得例子在知乎上。。。百度应该可以百度的到。
相关理论:
http://blog.csdn.net/cskchenshengkun/article/details/45770627
还有百度知道。
我只是搬砖工,能点赞的希望点赞,么么哒。饿死了,去吃饭了




原创粉丝点击