精华内容
下载资源
问答
  • 经常说的一个话题:Python多线程是假的多线程。具体python为什么在多线程方面比较弱呢?以下资料来自于网络的整理。全局解释器锁(GIL)Python代码的执行由Python虚拟机(解释器)来控制。Python在设计之初就考虑要...

    学习还是要多总结,不然老忘啊。

    经常说的一个话题:Python多线程是假的多线程。具体python为什么在多线程方面比较弱呢?

    以下资料来自于网络的整理。

    全局解释器锁(GIL)

    Python代码的执行由Python虚拟机(解释器)来控制。

    Python在设计之初就考虑要在主循环中,同时只有一个线程在执行,就像单CPU的系统中运行多个进程那样,内存中可以存放多个程序,但任意时刻,只有一个程序在CPU中运行。

    同样地,虽然Python解释器可以运行多个线程,只有一个线程在解释器中运行。

    对Python虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同时只有一个线程在运行。在多线程环境中,Python虚拟机按照以下方式执行。

    设置GIL。

    切换到一个线程去执行。

    运行。

    把线程设置为睡眠状态。

    解锁GIL。

    再次重复以上步骤。

    对所有面向I/O的(会调用内建的操作系统C代码的)程序来说,GIL会在这个I/O调用之前被释放,以允许其他线程在这个线程等待I/O的时候运行。如果某线程并未使用很多I/O操作,它会在自己的时间片内一直占用处理器和GIL。也就是说,I/O密集型的Python程序比计算密集型的Python程序更能充分利用多线程的好处。

    我们都知道,比方我有一个4核的CPU,那么这样一来,在单位时间内每个核只能跑一个线程,然后时间片轮转切换。但是Python不一样,它不管你有几个核,单位时间多个核只能跑一个线程,然后时间片轮转。看起来很不可思议?但是这就是GIL搞的鬼。任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。通常我们用的解释器是官方实现的CPython,要真正利用多核,除非重写一个不带GIL的解释器。

    即:

    你就不应该用Python写CPU密集型的代码…效率摆在那里…

    如果确实需要在CPU密集型的代码里用concurrent,就去用multiprocessing库。这个库是基于multi process实现了类multi thread的API接口,并且用pickle部分地实现了变量共享。

    再加一条,如果你不知道你的代码到底算CPU密集型还是IO密集型,教你个方法:multiprocessing这个module有一个dummy的sub module,它是基于multithread实现了multiprocessing的API。假设你使用的是multiprocessing的Pool,是使用多进程实现了concurrency

    from multiprocessing import Pool

    如果把这个代码改成下面这样,就变成多线程实现concurrency

    from multiprocessing.dummy import Pool

    两种方式都跑一下,哪个速度快用哪个就行了。

    此外,还有concurrent.futures这个东西,包含ThreadPoolExecutor和ProcessPoolExecutor,可能比multiprocessing更简单

    concurrent.futures

    concurrent.futures实例:

    python concurrent.futures https://www.cnblogs.com/kangoroo/p/7628092.html

    用c语言链接库来解决cpu密集型任务的多核多线程问题

    难道就如此?我们没有办法在Python中利用多核?当然可以!刚才的多进程算是一种解决方案,还有一种就是调用C语言的链接库。对所有面向I/O的(会调用内建的操作系统C代码的)程序来说,GIL会在这个I/O调用之前被释放,以允许其他线程在这个线程等待I/O的时候运行。我们可以把一些 计算密集型任务用C语言编写,然后把.so链接库内容加载到Python中,因为执行C代码,GIL锁会释放,这样一来,就可以做到每个核都跑一个线程的目的!

    总结

    Python多线程相当于单核多线程,多线程有两个好处:CPU并行,IO并行,单核多线程相当于自断一臂。所以,在Python中,可以使用多线程,但不要指望能有效利用多核。如果一定要通过多线程利用多核,那只能通过C扩展来实现,不过这样就失去了Python简单易用的特点。不过,也不用过于担心,Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。多个Python进程有各自独立的GIL锁,互不影响。

    参考

    展开全文
  • Intel多核多线程编程基础(Linux)
  • Intel多核多线程编程基础(windows)
  • 多核多线程的角度出发,介绍了操作系统多核的处理模式,并结合Java中的多线程技术,讨论了线程和线程池在Java中的应用.通过实例,展现了Java对多线程的强大支持,同时也讨论了Java5.0的一些和多线程相关的新增...
  • 示例代码展示了如果在windows实现多线程的同步,如何在多核CPU上开辟多个线程同时运行。
  • 在多核时代的程序员不能指望硬件和编译器来帮你搞定所有的事情,努力学习多核多线程编程的一些基础知识是很有必要的 前言:cpu的发展史实在是让人惊叹,买电脑 == cpu版本 现在好像有些明白为什么科技发烧友会穷了...

    在多核时代的程序员不能指望硬件和编译器来帮你搞定所有的事情,努力学习多核多线程编程的一些基础知识是很有必要的

    前言:cpu的发展史实在是让人惊叹,买电脑 == 高cpu版本

    现在好像有些明白为什么科技发烧友会穷了



    1、锁竞争(lock)
    单核中,使用了锁,其他等待获取锁的线程被阻塞 ,影响的只是枷锁和解锁的耗时,CPU始终运行。

    多核中,若2个(更多)线程使用同一把锁,则会导致CPU饥饿。实际还是串行化执行!

    2、线程分解和执行的区别:

    对单核CPU,对客户端软件,采用多线程,主要是 创建多线程将一些计算放在后台执行,而不影响用户交互操作。
    用户界面 & 其他计算 并行进行)提高用户的操作性能!

    多核中,分解多个线程使为了让计算分配到各CPU上执行。执行线程数量与CPU核数有关!如果线程数小于核数,某些CPU肯定处于空闲状态。


    3、CPU核负载平衡:

    单核中不考虑 负载平衡,

    多核中,必须考虑将各个线程计算量均衡到各CPU

    4、任务调度策略区别:
    单核中,任务调度主要考虑分时,某些任务的优先执行!常用:时间片轮转,优先级抢占!
    多核中,任务调度比单核有新的需求。要考虑 不同任务的耗时,和计算均衡!而总的调用操作系统不能掌握。需要程序员实现!


    5、CPU cache存取:
    CPU读取Cache时,以行为单位读取。导致2个线程同时写一个cache行。冲突!!【伪内存问题】
    单核机,不存在 伪内存问题
    多核机,存在伪内存问题!想办法,使不同的内存块映射到不同Cache行

    6、任务优先级抢先的区别
    单核CPU中,优先级抢占很常见的任务调度策略。
    多核CPU中,多个核可导致,低优先级和高优先级的任务可以同时运行。需要进一步改进 优先级调度策略
    cpu分一个优先级

    7、串行计算与并行计算、分布式计算的区别
    单核多线程编程中,都是串行算法。用不到并行计算,更用不到分布式计算
    多核编程中,多采用 并行计算 和 分布式计算

    其中:
    并行计算=并行设计模式+并行算法
    分布式计算复杂度 > 并行计算的复杂度 > 串行计算复杂度










    展开全文
  • 目前Python 提供了几种多线程实现方式 thread,threading,multithreading ,其中thread模块比较底层,而threading模块是对thread做了一些包装,可以更加方便的被使用。2.7版本之前python对线程的支持还不够完善,不...

    目前Python 提供了几种多线程实现方式 thread,threading,multithreading ,其中thread模块比较底层,而threading模块是对thread做了一些包装,可以更加方便的被使用。

    2.7版本之前python对线程的支持还不够完善,不能利用多核CPU,但是2.7版本的python中已经考虑改进这点,出现了multithreading 模块。threading模块里面主要是对一些线程的操作对象化,创建Thread的class。一般来说,使用线程有两种模式:

    A 创建线程要执行的函数,把这个函数传递进Thread对象里,让它来执行;

    B 继承Thread类,创建一个新的class,将要执行的代码 写到run函数里面。

    本文介绍两种实现方法。

    第一种 创建函数并且传入Thread 对象中

    t.py 脚本内容

    import threading,time

    from time import sleep, ctime

    def now() :

    return str( time.strftime( '%Y-%m-%d %H:%M:%S' , time.localtime() ) )

    def test(nloop, nsec):

    print 'start loop', nloop, 'at:', now()

    sleep(nsec)

    print 'loop', nloop, 'done at:', now()

    def main():

    print 'starting at:',now()

    threadpool=[]

    for i in xrange(10):

    th = threading.Thread(target= test,args= (i,2))

    threadpool.append(th)

    for th in threadpool:

    th.start()

    for th in threadpool :

    threading.Thread.join( th )

    print 'all Done at:', now()

    if __name__ == '__main__':

    main()

    执行结果:

    140609165458561.jpg

    thclass.py 脚本内容:

    import threading ,time

    from time import sleep, ctime

    def now() :

    return str( time.strftime( '%Y-%m-%d %H:%M:%S' , time.localtime() ) )

    class myThread (threading.Thread) :

    """docstring for myThread"""

    def __init__(self, nloop, nsec) :

    super(myThread, self).__init__()

    self.nloop = nloop

    self.nsec = nsec

    def run(self):

    print 'start loop', self.nloop, 'at:', ctime()

    sleep(self.nsec)

    print 'loop', self.nloop, 'done at:', ctime()

    def main():

    thpool=[]

    print 'starting at:',now()

    for i in xrange(10):

    thpool.append(myThread(i,2))

    for th in thpool:

    th.start()

    for th in thpool:

    th.join()

    print 'all Done at:', now()

    if __name__ == '__main__':

    main()

    执行结果:

    140609165458562.jpg

    Python 的详细介绍:请点这里

    Python 的下载地址:请点这里

    logo.gif

    展开全文
  • 学校关于多核编程课件, 很详细,很适合教学或者自学使用!
  • 该实例代码展示了如何根据CPU的核数开辟线程,并且实现线程同步。 #include "stdafx.h" #include "stdio.h" #include "windows.h" #include #include #define MAX_THREAD_COUNT 16 typedef struct _THREAD_...

    该实例代码展示了如何根据CPU的核数开辟多个线程,并且实现线程同步。

    #include "stdafx.h"
    #include "stdio.h"
    #include "windows.h"
    #include <conio.h>
    #include <process.h>
    #define MAX_THREAD_COUNT 16
    typedef struct _THREAD_PARAMS
    {
    UINT threadId;
    HANDLE threadHandle;
    HANDLE threadEvent;
    HANDLE threadDoneEvent;
    BOOL threadShouldExit;
    } THREAD_PARAMS;
    THREAD_PARAMS *ThreadParams = NULL;
    int ThreadCount = 0;
    BOOL success;
    BOOL StartWorkerThreads();
    void StopWorkerThreads();
    unsigned __stdcall ThreadFunc(void* pArguments);
    int main(int argc, char* argv[])
    {
    success = StartWorkerThreads();
    int threadIndex;
    for(threadIndex = 0; threadIndex < ThreadCount; threadIndex++)
    {
    THREAD_PARAMS *pThreadParams = &ThreadParams[threadIndex];
    // 利用SetEvent将ThreadEvent设置为触发状态,这样的话,等待ThreadEvent的线程就会处于触发状态。
    if (!SetEvent(pThreadParams->threadEvent))
    {
    printf("Error: SetEvent failed -- %u", GetLastError());
    success = FALSE;
    break;
    }
    }


    // Wait for all the worker threads to complete processing 


    for (threadIndex = 0; (threadIndex < ThreadCount) && success; threadIndex++)
    {
    DWORD result = WaitForSingleObject(ThreadParams[threadIndex].threadDoneEvent, INFINITE);
    if (result != WAIT_OBJECT_0)
    {
    printf("Error: WaitForSingleObject failed -- %u\n", GetLastError());
    success = FALSE;
    }
        }


          StopWorkerThreads();
     system("pause");
    }






    BOOL StartWorkerThreads()
    {
    StopWorkerThreads();


    // Find the number of processor cores available


    SYSTEM_INFO systemInfo;
    memset(&systemInfo, 0, sizeof(systemInfo));
    GetSystemInfo(&systemInfo);
    DWORD processorCount = systemInfo.dwNumberOfProcessors;


    // Start one worker thread per processor core, up to the specified limit


    int threadCount;
    if (processorCount < 1)
    threadCount = 1;
    else if (processorCount > MAX_THREAD_COUNT)
    threadCount = MAX_THREAD_COUNT;
    else
    threadCount = processorCount;


    // Allocate a THREAD_PARAM structure for each thread


    size_t allocBytes = threadCount * sizeof(THREAD_PARAMS);
    ThreadParams = (THREAD_PARAMS*) malloc(allocBytes);
    if (ThreadParams == NULL)
    {
    printf("Error: Alloc %u bytes failed", allocBytes);
    return FALSE;
    }


    memset(ThreadParams, 0, allocBytes);
    ThreadCount = threadCount;


    // Create worker threads

    for (int threadIndex = 0; threadIndex < threadCount; threadIndex++)
    {
    THREAD_PARAMS *pThreadParams = &ThreadParams[threadIndex];


    // The main thread signals a worker thread with this event
    //该threadEvent自动重置,且初始状态为无信号状态。
    pThreadParams->threadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (pThreadParams->threadEvent == NULL)
    {
    printf("Error: Create thread event failed -- %d", GetLastError());
    return FALSE;
    }


    // The worker thread signals the main thread with this event


    pThreadParams->threadDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (pThreadParams->threadDoneEvent == NULL)
    {
    printf("Error: Create thread event failed -- %d", GetLastError());
    return FALSE;
    }


    // Create the worker thread


    pThreadParams->threadShouldExit = FALSE;
    pThreadParams->threadHandle = (HANDLE) _beginthreadex(NULL, 0, ThreadFunc, pThreadParams, 0, &pThreadParams->threadId);
    if (pThreadParams->threadHandle == NULL)
    {
    printf("Error: Create thread failed -- %d", GetLastError());
    return FALSE;
    }
    }


    return TRUE;
    }


    //----------------------------------------------------------------------------
    //
    // Function    :  StopWorkerThreads
    //
    // Description :  Stop the worker threads started by StartWorkerThreads
    //
    //----------------------------------------------------------------------------
    void StopWorkerThreads(void)
    {
    if (ThreadParams != NULL)
    {
    for (int threadIndex = 0; threadIndex < ThreadCount; threadIndex++)
    {
    THREAD_PARAMS *pThreadParams = &ThreadParams[threadIndex];


    // Exit the thread


    if (pThreadParams->threadHandle != NULL)
    {
    pThreadParams->threadShouldExit = TRUE;
    //当线程结束运行的时候,利用SetEvent将threadEvent置于有信号的状态,
    //这样等待该threadEvent的线程将处于可调度的状态。
    if (!SetEvent(pThreadParams->threadEvent))  
    {
    printf("Error: SetEvent failed -- %d", GetLastError());
    }
    //当线程结束运行时,threadHandle将处于有信号状态,
    //这时候WaitForSingleObject函数将返回。
    WaitForSingleObject(pThreadParams->threadHandle, INFINITE);


    CloseHandle(pThreadParams->threadHandle);
    pThreadParams->threadHandle = NULL;
    pThreadParams->threadId = 0;
    }


    // Close notify event handle


    if (pThreadParams->threadEvent != NULL)
    {
    CloseHandle(pThreadParams->threadEvent);
    pThreadParams->threadEvent = NULL;
    }


    // Close processing complete event handle


    if (pThreadParams->threadDoneEvent != NULL)
    {
    CloseHandle(pThreadParams->threadDoneEvent);
    pThreadParams->threadDoneEvent = NULL;
    }
    }


    // Free THREAD_PARAMS structures


    free(ThreadParams);
    ThreadParams = NULL;
    }


    ThreadCount = 0;
    }




    unsigned __stdcall ThreadFunc(void* pArguments)
    {
    THREAD_PARAMS *pThreadParams = (THREAD_PARAMS*) pArguments;


    for (;;)
    {
    // 等待主线程将threadEvent置于有信号的状态。


    WaitForSingleObject(pThreadParams->threadEvent, INFINITE);
    if (pThreadParams->threadShouldExit)
    break;
    printf("hello!\n");

    // 通知主线程该线程运行结束。


    SetEvent(pThreadParams->threadDoneEvent);
    }


    return 0;
    }

    展开全文
  • 1. #pragma parallel for // 把for循环拆分成线程进行多核并发处理 2. #pragma parallel section { ...... } // 把代码段实现成线程进行多核并发处理 注: ● Visual Studio 下实现parallel需要打开O...
  • linux Kernel 多核多线程编程

    千次阅读 2013-09-19 19:09:28
    一.线程/进程 进程:资源管理的最小单位 线程:执行任务的最小单位 内核线程:内核空间创建,类似用户进程,但运行期间不能被抢断 用户线程:用户空间创建,拥有进程上下文,可调度可...@对称对处理:个cpu可以同
  • 该函数用于C函数的多线程编程中,对互斥锁的动态初始化。 不同的锁类型在试图对一个已经被锁定的互斥锁加锁时表现不同。 pthread_mutex_init()函数成功完成之后会返回零,其他任何返回值都表示出现了错误。 ...
  • Visual Studio 2010 可以采取的第一个操作是打开分析菜单,启动性能向导,然后选择"形象的多线程应用程序的行为"。到了Visual Studio 11情况发生变化了, Visual Studio 11 DP 性能向导中不存在可视化选项。它去了...
  • Visual Studio 2010 可以采取的第一个操作是打开分析菜单,启动性能向导,然后选择"形象的多线程应用程序的行为"。到了Visual Studio 11情况发生变化了, Visual Studio 11 DP 性能向导中不存在可视化选项。它去了...
  • 多核多线程技术编程

    千次阅读 2013-08-04 20:45:03
    几年之前,CPU的性能还主要取决于CPU的主频,经过超摩尔定律的发展后,没过多长时间CPU的主频...这意味着,要充分发挥多核CPU的性能,程序就必须采用多线程并发计算的方式,传统的串行程序将会极大地浪费多核CPU的运
  • 主要介绍了Linux多核多线程编程相关知识,以及如何借助工具进行优化,利用多线程提高程序性能。源码实例丰富,是多核多线程中初学者必备文档。
  • 写程序的多线程(可无限)和cpu的线程关系.(好像是超过cpu线程后就是模拟线程,阻塞的方式来模拟的.类似于mfc定时器) 不知道我说的对不对 那么硬件的主频又是什么?我对比5820k与6770k,有人说玩游戏6770主频好.多线程...
  • 多线程全面剖析 ... 并行计算与多核多线程编程 http://www.parallellabs.com/category/parallel-programming/ IBM developerWorks 中国 http://www.ibm.com/developerworks/cn/
  • 多核多线程复习

    2019-12-20 17:41:17
    北京科技大学天津学院17级多核多线程复习总结 lesson 1 1. 弗林分类 2. 进程与线程区别、线程状态 3. 片上多核处理器 4. 计算机硬件工艺发展顺序
  • 英特尔多核多线程技术中文版带书签
  • 多核多线程同步

    千次阅读 2012-10-21 01:14:15
    1.2.6 多核多线程同步 本书多线程的实现主要是在Windows平台上,因此WinThread和OpenMP是最主要的实现。多线程实现的核心是并行,并行的难点是同步。因为往往会导致程序出错或者效率不高。 那么什么是同步?...
  • 测试你对多核多线程的认知程度 目前,多核多线程编程已经成为一种趋势,但大部分程序员还没有从串行程序的思维中走出来。即使有些人对多核多线程的概念有所了解,但也是一知半解,写起多核多线程程序来总是束手束脚...
  • 为了使大学生或软件开发人员在面对多核体系结构,以及需要多 线程编程时有一本好的参考手册,同时...行多核多线程程序教学时提供一本有价值的参考书,英特尔软件学院 联合大学教师编纂了这本《英特尔多核/多线程技术》。
  • 铁路与多核多线程

    万次阅读 2009-04-05 23:03:00
    铁路与多核多线程 杨小华 多核多线程已经成为当前一个时髦的话题,早在2005年C++大师Herb Sutter就说过免费的午餐已经结束,并发编程的时代已经来临。从接触第一个多线程项目以来,已经是第三个年头了,一直想把这...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 50,300
精华内容 20,120
关键字:

多核多线程编程