<var id="fnfpo"><source id="fnfpo"></source></var>
<rp id="fnfpo"></rp>

<em id="fnfpo"><object id="fnfpo"><input id="fnfpo"></input></object></em>
<em id="fnfpo"><acronym id="fnfpo"></acronym></em>
  • <th id="fnfpo"><track id="fnfpo"></track></th>
  • <progress id="fnfpo"><track id="fnfpo"></track></progress>
  • <tbody id="fnfpo"><pre id="fnfpo"></pre></tbody>

  • 多核CPU下的多線程編程原來是這么回事...

    發布時間:2017-4-25 11:40    發布者:技術小白
    關鍵詞: cpu , 多線程
    多線程編程是現代軟件技術中很重要的一個環節。要弄懂多線程,這就要牽涉到多進程?當然,要了解到多進程,就要涉及到操作系統。不過大家也不要緊張,聽我慢慢道來。這其中的環節其實并不復雜。
    (1)單CPU下的多線程
    在沒有出現多核CPU之前,我們的計算資源是唯一的。如果系統中有多個任務要處理的話,那么就需要按照某種規則依次調度這些任務進行處理。什么規則呢?可以是一些簡單的調度方法,比如說

        1)按照優先級調度
        2)按照FIFO調度
        3)按照時間片調度等等
    當然,除了CPU資源之外,系統中還有一些其他的資源需要共享,比如說內存、文件、端口、socket等。既然前面說到系統中的資源是有限的,那么獲取這些資源的最小單元體是什么呢,其實就是進程。

    舉個例子來說,在Linux上面每一個享有資源的個體稱為task_struct,實際上和我們說的進程是一樣的。我們可以看看task_struct(linux 0.11代碼)都包括哪些內容,
    1. struct task_struct {  
    2. /* these are hardcoded - don't touch */  
    3.     long state; /* -1 unrunnable, 0 runnable, >0 stopped */  
    4.     long counter;  
    5.     long priority;  
    6.     long signal;  
    7.     struct sigaction sigaction[32];  
    8.     long blocked;   /* bitmap of masked signals */  
    9. /* various fields */  
    10.     int exit_code;  
    11.     unsigned long start_code,end_code,end_data,brk,start_stack;  
    12.     long pid,father,pgrp,session,leader;  
    13.     unsigned short uid,euid,suid;  
    14.     unsigned short gid,egid,sgid;  
    15.     long alarm;  
    16.     long utime,stime,cutime,cstime,start_time;  
    17.     unsigned short used_math;  
    18. /* file system info */  
    19.     int tty;        /* -1 if no tty, so it must be signed */  
    20.     unsigned short umask;  
    21.     struct m_inode * pwd;  
    22.     struct m_inode * root;  
    23.     struct m_inode * executable;  
    24.     unsigned long close_on_exec;  
    25.     struct file * filp[NR_OPEN];  
    26. /* ldt for this task 0 - zero 1 - cs 2 - ds&ss */  
    27.     struct desc_struct ldt[3];  
    28. /* tss for this task */  
    29.     struct tss_struct tss;  
    30. };  
    每一個task都有自己的pid,在系統中資源的分配都是按照pid進行處理的。這也就說明,進程確實是資源分配的主體。

    這時候,可能有朋友會問了,既然task_struct是資源分配的主體,那為什么又出來thread?為什么系統調度的時候是按照thread調度,而不是按照進程調度呢?原因其實很簡單,進程之間的數據溝通非常麻煩,因為我們之所以把這些進程分開,不正是希望它們之間不要相互影響嘛。

    假設是兩個進程之間數據傳輸,那么需要如果需要對共享數據進行訪問需要哪些步驟呢

    1)創建共享內存  
    2)訪問共享內存->系統調用->讀取數據
    3)寫入共享內存->系統調用->寫入數據
    要是寫個代碼,大家可能就更明白了,
    1. #include   
    2. #include   
    3.   
    4. int value = 10;  
    5.   
    6. int main(int argc, char* argv[])  
    7. {  
    8.     int pid = fork();  
    9.     if(!pid){  
    10.         Value = 12;  
    11.         return 0;  
    12.     }  
    13.     printf("value = %d\n", value);  
    14.     return 1;  
    15. }  
    上面的代碼是一個創建子進程的代碼,我們發現打印的value數值還是10。盡管中間創建了子進程,修改了value的數值,但是我們發現打印下來的數值并沒有發生改變,這就說明了不同的進程之間內存上是不共享的。
    那么,如果修改成thread有什么好處呢?其實最大的好處就是每個thread除了享受單獨cpu調度的機會,還能共享每個進程下的所有資源。要是調度的單位是進程,那么每個進程只能干一件事情,但是進程之間是需要相互交互數據的,而進程之間的數據都需要系統調用才能應用,這在無形之中就降低了數據的處理效率。
    (2)多核CPU下的多線程
    沒有出現多核之前,我們的CPU實際上是按照某種規則對線程依次進行調度的。在某一個特定的時刻,CPU執行的還是某一個特定的線程。然而,現在有了多核CPU,一切變得不一樣了,因為在某一時刻很有可能確實是n個任務在n個核上運行。我們可以編寫一個簡單的open mp測試一下,如果還是一個核,運行的時間就應該是一樣的。
    1. #include   
    2. #define MAX_VALUE 10000000  
    3.   
    4. double _test(int value)  
    5. {  
    6.     int index;  
    7.     double result;  
    8.   
    9.     result = 0.0;  
    10.     for(index = value + 1; index < MAX_VALUE; index +=2 )  
    11.         result += 1.0 / index;  
    12.   
    13.     return result;  
    14. }  
    15.   
    16. void test()  
    17. {  
    18.     int index;  
    19.     int time1;  
    20.     int time2;  
    21.     double value1,value2;  
    22.     double result[2];  
    23.   
    24.     time1 = 0;  
    25.     time2 = 0;  
    26.   
    27.     value1 = 0.0;  
    28.     time1 = GetTickCount();  
    29.     for(index = 1; index < MAX_VALUE; index ++)  
    30.         value1 += 1.0 / index;  
    31.   
    32.     time1 = GetTickCount() - time1;  
    33.   
    34.     value2 = 0.0;  
    35.     memset(result , 0, sizeof(double) * 2);  
    36.     time2 = GetTickCount();  
    37.   
    38. #pragma omp parallel for  
    39.     for(index = 0; index < 2; index++)  
    40.         result[index] = _test(index);  
    41.   
    42.     value2 = result[0] + result[1];  
    43.     time2 = GetTickCount() - time2;  
    44.   
    45.     printf("time1 = %d,time2 = %d\n",time1,time2);  
    46.     return;  
    47. }  
    (3)多線程編程
    為什么要多線程編程呢?這其中的原因很多,我們可以舉例解決

    1)有的是為了提高運行的速度,比如多核cpu下的多線程

    2)有的是為了提高資源的利用率,比如在網絡環境下下載資源時,時延常常很高,我們可以通過不同的thread從不同的地方獲取資源,這樣可以提高效率

    3)有的為了提供更好的服務,比如說是服務器

    4)其他需要多線程編程的地方等等


    本文地址:http://www.portaltwn.com/thread-362074-1-1.html     【打印本頁】

    本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
    您需要登錄后才可以發表評論 登錄 | 立即注冊

    廠商推薦

    • Microchip視頻專區
    • Dev Tool Bits——使用MPLAB® Discover瀏覽資源
    • Dev Tool Bits——使用條件軟件斷點宏來節省時間和空間
    • Dev Tool Bits——使用DVRT協議查看項目中的數據
    • Dev Tool Bits——使用MPLAB® Data Visualizer進行功率監視
    • 貿澤電子(Mouser)專區
    關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
    電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
    快速回復 返回頂部 返回列表
    精品一区二区三区自拍图片区_国产成人亚洲精品_亚洲Va欧美va国产综合888_久久亚洲国产精品五月天婷