• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            牽著老婆滿街逛

            嚴(yán)以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            管理處理器的親和性(affinity)

            轉(zhuǎn)載自:http://www.ibm.com/developerworks/cn/linux/l-affinity.html


            簡單地說,CPU 親和性(affinity) 就是進(jìn)程要在某個(gè)給定的 CPU 上盡量長時(shí)間地運(yùn)行而不被遷移到其他處理器的傾向性。Linux 內(nèi)核進(jìn)程調(diào)度器天生就具有被稱為 軟 CPU 親和性(affinity) 的特性,這意味著進(jìn)程通常不會(huì)在處理器之間頻繁遷移。這種狀態(tài)正是我們希望的,因?yàn)檫M(jìn)程遷移的頻率小就意味著產(chǎn)生的負(fù)載小。

            2.6 版本的 Linux 內(nèi)核還包含了一種機(jī)制,它讓開發(fā)人員可以編程實(shí)現(xiàn) 硬 CPU 親和性(affinity)。這意味著應(yīng)用程序可以顯式地指定進(jìn)程在哪個(gè)(或哪些)處理器上運(yùn)行。

            什么是 Linux 內(nèi)核硬親和性(affinity)?

            在 Linux 內(nèi)核中,所有的進(jìn)程都有一個(gè)相關(guān)的數(shù)據(jù)結(jié)構(gòu),稱為 task_struct。這個(gè)結(jié)構(gòu)非常重要,原因有很多;其中與 親和性(affinity)相關(guān)度最高的是 cpus_allowed 位掩碼。這個(gè)位掩碼由 n 位組成,與系統(tǒng)中的 n 個(gè)邏輯處理器一一對(duì)應(yīng)。 具有 4 個(gè)物理 CPU 的系統(tǒng)可以有 4 位。如果這些 CPU 都啟用了超線程,那么這個(gè)系統(tǒng)就有一個(gè) 8 位的位掩碼。

            如果為給定的進(jìn)程設(shè)置了給定的位,那么這個(gè)進(jìn)程就可以在相關(guān)的 CPU 上運(yùn)行。因此,如果一個(gè)進(jìn)程可以在任何 CPU 上運(yùn)行,并且能夠根據(jù)需要在處理器之間進(jìn)行遷移,那么位掩碼就全是 1。實(shí)際上,這就是 Linux 中進(jìn)程的缺省狀態(tài)。

            Linux 內(nèi)核 API 提供了一些方法,讓用戶可以修改位掩碼或查看當(dāng)前的位掩碼:

            • sched_set_affinity() (用來修改位掩碼)
            • sched_get_affinity() (用來查看當(dāng)前的位掩碼)

            注意,cpu_affinity 會(huì)被傳遞給子線程,因此應(yīng)該適當(dāng)?shù)卣{(diào)用 sched_set_affinity

            為什么應(yīng)該使用硬親和性(affinity)?

            通常 Linux 內(nèi)核都可以很好地對(duì)進(jìn)程進(jìn)行調(diào)度,在應(yīng)該運(yùn)行的地方運(yùn)行進(jìn)程(這就是說,在可用的處理器上運(yùn)行并獲得很好的整體性能)。內(nèi)核包含了一些用來檢測(cè) CPU 之間任務(wù)負(fù)載遷移的算法,可以啟用進(jìn)程遷移來降低繁忙的處理器的壓力。

            一般情況下,在應(yīng)用程序中只需使用缺省的調(diào)度器行為。然而,您可能會(huì)希望修改這些缺省行為以實(shí)現(xiàn)性能的優(yōu)化。讓我們來看一下使用硬親和性(affinity) 的 3 個(gè)原因。

            原因 1. 有大量計(jì)算要做

            基于大量計(jì)算的情形通常出現(xiàn)在科學(xué)和理論計(jì)算中,但是通用領(lǐng)域的計(jì)算也可能出現(xiàn)這種情況。一個(gè)常見的標(biāo)志是您發(fā)現(xiàn)自己的應(yīng)用程序要在多處理器的機(jī)器上花費(fèi)大量的計(jì)算時(shí)間。

            原因 2. 您在測(cè)試復(fù)雜的應(yīng)用程序

            測(cè)試復(fù)雜軟件是我們對(duì)內(nèi)核的親和性(affinity)技術(shù)感興趣的另外一個(gè)原因。考慮一個(gè)需要進(jìn)行線性可伸縮性測(cè)試的應(yīng)用程序。有些產(chǎn)品聲明可以在 使用更多硬件 時(shí)執(zhí)行得更好。

            我們不用購買多臺(tái)機(jī)器(為每種處理器配置都購買一臺(tái)機(jī)器),而是可以:

            • 購買一臺(tái)多處理器的機(jī)器
            • 不斷增加分配的處理器
            • 測(cè)量每秒的事務(wù)數(shù)
            • 評(píng)估結(jié)果的可伸縮性

            如果應(yīng)用程序隨著 CPU 的增加可以線性地伸縮,那么每秒事務(wù)數(shù)和 CPU 個(gè)數(shù)之間應(yīng)該會(huì)是線性的關(guān)系(例如斜線圖 —— 請(qǐng)參閱下一節(jié)的內(nèi)容)。這樣建模可以確定應(yīng)用程序是否可以有效地使用底層硬件。

            Amdahl 法則

            Amdahl 法則是有關(guān)使用并行處理器來解決問題相對(duì)于只使用一個(gè)串行處理器來解決問題的加速比的法則。加速比(Speedup) 等于串行執(zhí)行(只使用一個(gè)處理器)的時(shí)間除以程序并行執(zhí)行(使用多個(gè)處理器)的時(shí)間:

                  T(1)
                        S = ------
                        T(j)
                        

            其中 T(j) 是在使用 j 個(gè)處理器執(zhí)行程序時(shí)所花費(fèi)的時(shí)間。

            Amdahl 法則說明這種加速比在現(xiàn)實(shí)中可能并不會(huì)發(fā)生,但是可以非常接近于該值。對(duì)于通常情況來說,我們可以推論出每個(gè)程序都有一些串行的組件。隨著問題集不斷變大,串行組件最終會(huì)在優(yōu)化解決方案時(shí)間方面達(dá)到一個(gè)上限。

            Amdahl 法則在希望保持高 CPU 緩存命中率時(shí)尤其重要。如果一個(gè)給定的進(jìn)程遷移到其他地方去了,那么它就失去了利用 CPU 緩存的優(yōu)勢(shì)。實(shí)際上,如果正在使用的 CPU 需要為自己緩存一些特殊的數(shù)據(jù),那么所有其他 CPU 都會(huì)使這些數(shù)據(jù)在自己的緩存中失效。

            因此,如果有多個(gè)線程都需要相同的數(shù)據(jù),那么將這些線程綁定到一個(gè)特定的 CPU 上是非常有意義的,這樣就確保它們可以訪問相同的緩存數(shù)據(jù)(或者至少可以提高緩存的命中率)。否則,這些線程可能會(huì)在不同的 CPU 上執(zhí)行,這樣會(huì)頻繁地使其他緩存項(xiàng)失效。

            原因 3. 您正在運(yùn)行時(shí)間敏感的、決定性的進(jìn)程

            我們對(duì) CPU 親和性(affinity)感興趣的最后一個(gè)原因是實(shí)時(shí)(對(duì)時(shí)間敏感的)進(jìn)程。例如,您可能會(huì)希望使用硬親和性(affinity)來指定一個(gè) 8 路主機(jī)上的某個(gè)處理器,而同時(shí)允許其他 7 個(gè)處理器處理所有普通的系統(tǒng)調(diào)度。這種做法確保長時(shí)間運(yùn)行、對(duì)時(shí)間敏感的應(yīng)用程序可以得到運(yùn)行,同時(shí)可以允許其他應(yīng)用程序獨(dú)占其余的計(jì)算資源。

            下面的樣例應(yīng)用程序顯示了這是如何工作的。

            如何利用硬親和性(affinity)

            現(xiàn)在讓我們來設(shè)計(jì)一個(gè)程序,它可以讓 Linux 系統(tǒng)非常繁忙。可以使用前面介紹的系統(tǒng)調(diào)用和另外一些用來說明系統(tǒng)中有多少處理器的 API 來構(gòu)建這個(gè)應(yīng)用程序。實(shí)際上,我們的目標(biāo)是編寫這樣一個(gè)程序:它可以讓系統(tǒng)中的每個(gè)處理器都繁忙幾秒鐘。可以從后面的“下載”一節(jié)中 下載樣例程序


            清單 1. 讓處理器繁忙
                        /* This method will create threads, then bind each to its own cpu. */
                        bool do_cpu_stress(int numthreads)
                        {
                        int ret = TRUE;
                        int created_thread = 0;
                        /* We need a thread for each cpu we have... */
                        while ( created_thread < numthreads - 1 )
                        {
                        int mypid = fork();
                        if (mypid == 0) /* Child process */
                        {
                        printf("\tCreating Child Thread: #%i\n", created_thread);
                        break;
                        }
                        else /* Only parent executes this */
                        {
                        /* Continue looping until we spawned enough threads! */ ;
                        created_thread++;
                        }
                        }
                        /* NOTE: All threads execute code from here down! */
                        

            正如您可以看到的一樣,這段代碼只是通過 fork 調(diào)用簡單地創(chuàng)建一組線程。每個(gè)線程都執(zhí)行這個(gè)方法中后面的代碼。現(xiàn)在我們讓每個(gè)線程都將親和性(affinity)設(shè)置為自己的 CPU。


            清單 2. 為每個(gè)線程設(shè)置 CPU 親和性(affinity)
                        cpu_set_t mask;
                        /* CPU_ZERO initializes all the bits in the mask to zero. */
                        CPU_ZERO( &mask );
                        /* CPU_SET sets only the bit corresponding to cpu. */
                        CPU_SET( created_thread, &mask );
                        /* sched_setaffinity returns 0 in success */
                        if( sched_setaffinity( 0, sizeof(mask), &mask ) == -1 )
                        {
                        printf("WARNING: Could not set CPU Affinity, continuing...\n");
                        }
                        

            如果程序可以執(zhí)行到這兒,那么我們的線程就已經(jīng)設(shè)置了自己的親和性(affinity)。調(diào)用 sched_setaffinity 會(huì)設(shè)置由 pid 所引用的進(jìn)程的 CPU 親和性(affinity)掩碼。如果 pid 為 0,那么就使用當(dāng)前進(jìn)程。

            親和性(affinity)掩碼是使用在 mask 中存儲(chǔ)的位掩碼來表示的。最低位對(duì)應(yīng)于系統(tǒng)中的第一個(gè)邏輯處理器,而最高位則對(duì)應(yīng)于系統(tǒng)中最后一個(gè)邏輯處理器。

            每個(gè)設(shè)置的位都對(duì)應(yīng)一個(gè)可以合法調(diào)度的 CPU,而未設(shè)置的位則對(duì)應(yīng)一個(gè)不可調(diào)度的 CPU。換而言之,進(jìn)程都被綁定了,只能在那些對(duì)應(yīng)位被設(shè)置了的處理器上運(yùn)行。通常,掩碼中的所有位都被置位了。這些線程的親和性(affinity)都會(huì)傳遞給從它們派生的子進(jìn)程中。

            注意不應(yīng)該直接修改位掩碼。應(yīng)該使用下面的宏。雖然在我們的例子中并沒有全部使用這些宏,但是在本文中還是詳細(xì)列出了這些宏,您在自己的程序中可能需要這些宏。


            清單 3. 間接修改位掩碼的宏
                        void CPU_ZERO (cpu_set_t *set)
                        這個(gè)宏對(duì) CPU 集 set 進(jìn)行初始化,將其設(shè)置為空集。
                        void CPU_SET (int cpu, cpu_set_t *set)
                        這個(gè)宏將 cpu 加入 CPU 集 set 中。
                        void CPU_CLR (int cpu, cpu_set_t *set)
                        這個(gè)宏將 cpu 從 CPU 集 set 中刪除。
                        int CPU_ISSET (int cpu, const cpu_set_t *set)
                        如果 cpu 是 CPU 集 set 的一員,這個(gè)宏就返回一個(gè)非零值(true),否則就返回零(false)。
                        

            對(duì)于本文來說,樣例代碼會(huì)繼續(xù)讓每個(gè)線程都執(zhí)行某些計(jì)算量較大的操作。


            清單 4. 每個(gè)線程都執(zhí)行一個(gè)計(jì)算敏感的操作
                        /* Now we have a single thread bound to each cpu on the system */
                        int computation_res = do_cpu_expensive_op(41);
                        cpu_set_t mycpuid;
                        sched_getaffinity(0, sizeof(mycpuid), &mycpuid);
                        if ( check_cpu_expensive_op(computation_res) )
                        {
                        printf("SUCCESS: Thread completed, and PASSED integrity check!\n",
                        mycpuid);
                        ret = TRUE;
                        }
                        else
                        {
                        printf("FAILURE: Thread failed integrity check!\n",
                        mycpuid);
                        ret = FALSE;
                        }
                        return ret;
                        }
                        

            現(xiàn)在您已經(jīng)了解了在 Linux 2.6 版本的內(nèi)核中設(shè)置 CPU 親和性(affinity)的基本知識(shí)。接下來,我們使用一個(gè) main 程序來封裝這些方法,它使用一個(gè)用戶指定的參數(shù)來說明要讓多少個(gè) CPU 繁忙。我們可以使用另外一個(gè)方法來確定系統(tǒng)中有多少個(gè)處理器:

            int NUM_PROCS = sysconf(_SC_NPROCESSORS_CONF);

            這個(gè)方法讓程序能夠自己確定要讓多少個(gè)處理器保持繁忙,例如缺省讓所有的處理器都處于繁忙狀態(tài),并允許用戶指定系統(tǒng)中實(shí)際處理器范圍的一個(gè)子集。

            運(yùn)行樣例程序

            當(dāng)運(yùn)行前面介紹的 樣例程序 時(shí),可以使用很多工具來查看 CPU 是否是繁忙的。如果只是簡單地進(jìn)行測(cè)試,可以使用 Linux 命令top。在運(yùn)行 top 命令時(shí)按下 “1” 鍵,可以看到每個(gè) CPU 執(zhí)行進(jìn)程所占用的百分比。

            結(jié)束語

            這個(gè)樣例程序雖然非常簡單,但是它卻展示了使用 Linux 內(nèi)核中實(shí)現(xiàn)的硬親和性(affinity)的基本知識(shí)。(任何使用這段代碼的應(yīng)用程序都無疑會(huì)做一些更有意義的事情。)了解了 CPU 親和性(affinity)內(nèi)核 API 的基本知識(shí),您就可以從復(fù)雜的應(yīng)用程序中榨取出最后一點(diǎn)兒性能了。


            下載

            描述 名字 大小 下載方法
            Sample app using CPU affinity kernel API thrasher.zip 3 KB FTP

            關(guān)于下載方法的信息


            參考資料

            學(xué)習(xí)

            獲得產(chǎn)品和技術(shù)

            討論

            關(guān)于作者

            Eli Dow 是位于 Poughkeepsie, NY. 的 IBM Linux Test and Integration Center 的一名軟件工程師。他擁有 Clarkson 大學(xué)的計(jì)算機(jī)科學(xué)和心理學(xué)學(xué)士學(xué)位,以及計(jì)算機(jī)科學(xué)碩士學(xué)位。他的興趣包括 GNOME 桌面、人與計(jì)算機(jī)的交互以及 Linux 系統(tǒng)編程。您可以通過emdow@us.ibm.com 與 Eli 聯(lián)系。


            posted on 2010-11-01 03:05 楊粼波 閱讀(908) 評(píng)論(0)  編輯 收藏 引用


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            91久久精品国产免费直播| 精品综合久久久久久88小说 | 久久亚洲AV成人出白浆无码国产| 国产精品久久新婚兰兰| 久久人妻少妇嫩草AV无码蜜桃| 2020最新久久久视精品爱| 国产精品午夜久久| 伊人久久大香线蕉亚洲| 麻豆精品久久久一区二区| 一级做a爰片久久毛片免费陪 | 国产欧美久久一区二区| 狠狠精品久久久无码中文字幕 | 青青久久精品国产免费看| 中文字幕无码免费久久| 久久国产热精品波多野结衣AV| 精品久久人人做人人爽综合| 中文国产成人精品久久亚洲精品AⅤ无码精品| 国产精品久久久久久久久久影院| 久久亚洲春色中文字幕久久久| 久久综合色之久久综合| 久久精品人成免费| 人妻丰满?V无码久久不卡| 国产午夜精品理论片久久影视| 777午夜精品久久av蜜臀| 久久久久黑人强伦姧人妻| 99久久超碰中文字幕伊人| A级毛片无码久久精品免费| 久久久久亚洲精品天堂久久久久久 | 久久精品国产亚洲av麻豆蜜芽| 国产精品99久久精品爆乳| 久久香蕉超碰97国产精品| 久久无码AV中文出轨人妻| 久久强奷乱码老熟女| 国内精品久久久久久久久 | 久久久青草久久久青草| 2021国内久久精品| 亚洲精品高清一二区久久| 无码乱码观看精品久久| 欧美亚洲国产精品久久高清| 亚洲人AV永久一区二区三区久久| 亚洲欧美国产精品专区久久|