QNX system architecture -- Chapter 5 Multicore Processing

QNX Neutrino RTOS可以在單核或多核系統上運行。 多處理系統可以採用以下形式:

Discrete or traditional

具有單獨物理處理器的系統通過板級總線連接在多處理模式下。

Multicore

一個芯片,其中一個物理處理器具有多個CPU,通過芯片級總線互連。

多核處理器通過併發性提供更高的計算能力,提供更高的系統密度,並以比單處理器芯片更低的時鐘速度運行。多核處理器還可以降低散熱,功耗和電路板面積(從而降低系統成本)。

多處理包括幾種操作模式:

Asymmetric multiprocessing (AMP):

在每個CPU上運行單獨的OS或相同OS的單獨實例

Symmetric multiprocessing (SMP):

OS的單個實例化同時管理所有CPU,應用程序可以浮動到它們中的任何一個。

Bound multiprocessing (BMP):

OS的單個實例化同時管理所有CPU,但每個應用程序都鎖定到特定的CPU。

注意:要確定系統上有多少處理器,請查看系統頁面的num_cpu條目。 有關更多信息,請參閱構建嵌入式系統的系統頁面章節。

Asymmetric multiprocessing (AMP)

非對稱多處理提供了與傳統單處理器系統類似的執行環境。它爲移植遺留代碼提供了相對簡單的途徑,並提供了一種控制CPU使用方式的直接機制。在大多數情況下,它允許您使用標準調試工具和技術。

AMP can be:

• homogeneous —每個CPU運行相同類型和版本的操作系統

• heterogeneous —每個CPU運行不同的操作系統或同一操作系統的不同版本

QNX Neutrino的分佈式編程模型使您可以在同構環境中充分利用多個CPU。在一個CPU上運行的應用程序可以與其他CPU上的應用程序和系統服務(例如,設備驅動程序,協議棧)透明地通信,而不需要傳統形式的處理器間通信所強加的高CPU利用率。

在異構系統中,您必須實現專有通信方案,或者選擇兩個共享公共基礎結構(可能基於IP)的操作系統,以進行處理器間通信。爲了幫助避免資源衝突,操作系統還應提供訪問共享硬件組件的標準化機制。

使用AMP,您可以決定應用程序使用的共享硬件資源如何在CPU之間進行劃分。通常,此資源分配在引導期間靜態發生,包括物理內存分配,外設使用和中斷處理。雖然系統可以動態分配資源,但這樣做會導致CPU之間的複雜協調。

在AMP系統中,進程始終在同一CPU上運行,即使其他CPU空閒也是如此。結果,一個CPU可能最終被低估或過度使用。爲了解決該問題,系統可以允許應用程序從CPU動態遷移到另一個。但是,這樣做可能涉及複雜的狀態信息檢查點或可能的服務中斷,因爲應用程序在一個CPU上停止並在另一個CPU上重新啓動。此外,如果CPU運行不同的操作系統,這種遷移即使不是不可能,也很困難。

Symmetric multiprocessing (SMP)

在多核設計中分配資源可能很困難,尤其是當多個軟件組件不知道其他組件如何使用這些資源時。

對稱多處理通過在所有系統的CPU上僅運行QNX Neutrino RTOS的一個副本來解決該問題。由於操作系統始終可以深入瞭解所有系統元素,因此可以在很少或沒有來自應用程序設計人員的輸入的情況下在多個CPU上分配資源。此外,QNX Neutrino提供內置的標準化原語,例如pthread_mutex_lock(),pthread_mutex_unlock(),pthread_spin_lock()和pthread_spin_unlock(),讓多個應用程序可以安全輕鬆地共享這些資源。

通過僅運行QNX Neutrino的一個副本,SMP可以動態地將資源分配給特定應用程序而不是CPU,從而可以更好地利用可用處理能力。它還允許系統跟蹤工具爲多處理系統整體收集操作統計信息和應用程序交互,爲您提供有關如何優化和調試應用程序的寶貴見解。

例如,IDE中的System Profiler可以跟蹤從一個CPU到另一個CPU的線程遷移,以及OS原語使用,調度事件,應用程序到應用程序消息傳遞和其他事件,所有這些都具有高分辨率時間戳。由於您使用標準OS原語而不是複雜的IPC機制,因此應用程序同步也變得更加容易。

QNX Neutrino允許應用程序中的執行線程在任何CPU上同時運行,使得芯片的整個計算能力始終可供應用程序使用。QNX Neutrino的搶佔和線程優先級排序功能可幫助您確保CPU週期進入最需要它們的應用程序。

Booting an x86 SMP system

微內核本身包含非常少的硬件或系統特定代碼。決定系統功能的代碼在啓動程序中被隔離,啓動程序負責初始化系統,確定可用內存等。收集的信息被放入微內核和所有進程可用的內存表中(在讀取時) - 只是基礎)。

startup-x86 程序旨在用於支持統一可擴展固件接口的系統。該啓動程序負責:

• 確定處理器數量
•確定本地和I / O APIC的地址
•初始化每個額外的處理器

復位後,只有一個處理器將執行復位代碼。 該處理器稱爲啓動處理器(BP)。 對於找到的每個其他處理器,運行startup-x86代碼的BP將:

•初始化處理器
•將其切換到32位保護模式
•爲處理器分配自己的頁面目錄
•設置處理器在禁用中斷的情況下旋轉,等待內核釋放

How the SMP microkernel works

一旦附加處理器已經發布並且正在運行,所有處理器都被認爲是用於線程調度的對等體。

Scheduling

調度策略遵循與單處理器系統相同的規則。也就是說,優先級最高的線程將在可用的處理器上運行。如果新線程準備好作爲系統中的最高優先級線程運行,它將被分派到適當的處理器。如果選擇多個處理器作爲潛在目標,則微內核將嘗試將線程分派到上次運行的處理器。此親和關係用於嘗試減少從一個處理器到另一個處理器的線程遷移,這可能會影響緩存性能。

在SMP系統中,調度程序在確定如何調度其他線程時具有一定的靈活性,着眼於優化高速緩存使用並最小化線程遷移。這可能意味着某些處理器將運行優先級較低的線程,而優先級較高的線程正在等待它上次運行的處理器上運行。下一次運行較低優先級線程的處理器做出調度決策時,它將選擇優先級較高的線程。

在任何情況下,保證在單處理器系統上實施的實時調度規則在SMP系統上得到支持。

Kernel locking

在單處理器系統中,一次只允許一個線程在微內核中執行。大多數內核操作的持續時間很短(在奔騰級處理器上通常爲幾微秒)。 微內核還設計爲完全可搶佔並可重新啓動,以用於需要更多時間的操作。這種設計保留了微內核精簡而快速,無需大量精細鎖。有趣的是,通過內核在主代碼路徑中放置許多鎖會明顯降低內核的速度。每個鎖通常涉及處理器總線事務,這可能導致處理器停頓。

在SMP系統中,QNX Neutrino在可搶佔和可重新啓動的內核中只保留了一個線程的這種理念。 可以在任何處理器上輸入微內核,但是一次只允許一個處理器訪問。

對於大多數系統,在微內核中花費的時間僅佔處理器工作負載的一小部分。因此,雖然會發生衝突,他們應該比一般例外更多。。對於微內核尤其如此,其中傳統的OS服務(如文件系統)是獨立的進程而不是內核本身的一部分。

Interprocessor interrupts (IPIs)

處理器通過IPI(處理器間中斷)相互通信。IPI可以有效地調度和控制多個處理器上的線程。例如,在以下情況下,通常需要對另一個處理器進行IPI:

•優先級較高的線程準備就緒
•在另一個處理器上運行的線程被信號命中

•取消在另一個處理器上運行的線程
•銷燬在另一個處理器上運行的線程

Critical sections

爲了控制對它們之間共享的數據結構的訪問,線程和進程使用互斥鎖,condvars和信號量的標準POSIX原語。這些工作在SMP系統中沒有變化。

許多實時系統還需要保護對中斷處理程序和擁有處理程序的線程之間的共享數據結構的訪問。 線程之間使用的傳統POSIX原語不能供中斷處理程序使用。 這裏有兩種解決方案:

    1. 一種是從中斷處理程序中刪除所有工作,而是在線程時執行所有工作。鑑於我們的快速線程調度,這是一個非常可行的解決方案。

    2. 在運行QNX Neutrino RTOS的單處理器系統中,中斷處理程序可以搶佔線程,但線程永遠不會搶佔中斷處理程序。這允許線程通過在非常短的時間內禁用和啓用中斷來保護自己免受中斷處理程序的影響。

非SMP系統上的線程使用以下形式的代碼保護自己:

InterruptDisable()
// critical section
InterruptEnable()
Or:
InterruptMask(intr)
// critical section
InterruptUnmask(intr)

不幸的是,這個代碼在SMP系統上會失敗,因爲線程可能在一個處理器上運行而中斷處理程序同時在另一個處理器上運行!

一種解決方案是將線程鎖定到特定處理器(請參閱本章後面的“Bound Multiprocessing (BMP)”)。

更好的解決方案是使用線程和中斷處理程序可用的新排除鎖。 這由以下原語提供,它們適用於單處理器和SMP機器:

InterruptLock(intrspin_t* spinlock )

嘗試獲取一個自旋鎖,一個在中斷處理程序和線程之間共享的變量。 代碼將在緊密循環中旋轉,直到獲得鎖定。禁用中斷後,代碼將獲取鎖定(如果它是由線程獲取的)。必須儘快釋放鎖(通常在幾行C代碼中沒有任何循環)。

InterruptUnlock(intrspin_t* spinlock )

釋放鎖定並啓用中斷。

 

在非SMP系統上,不需要自旋鎖。

Bound multiprocessing (BMP)

綁定多處理提供非對稱多處理模型的調度控制,同時保留對稱多處理的硬件抽象和管理。

BMP與SMP類似,但您可以指定線程可以運行的處理器。您可以在同一系統上同時使用SMP和BMP,允許某些線程從一個處理器遷移到另一個處理器,而其他線程僅限於一個或多個處理器。

與SMP一樣,操作系統的單個副本維護所有系統資源的整體視圖,允許它們在應用程序之間動態分配和共享。但是,在應用程序初始化期間,系統設計人員確定的設置會強制所有應用程序的線程僅在指定的CPU上執行。

與完整的浮動SMP操作相比,此方法具有以下幾個優點:

  • 它通過允許共享相同數據集的應用程序僅在同一CPU上運行,消除了可能降低SMP系統性能的緩存抖動。

  • 它提供比SMP更簡單的應用程序調試,因爲應用程序中的所有執行線程都在單個CPU上運行。

  • 通過讓共享數據在單個CPU上運行,它可以幫助使用差技術同步共享數據的舊應用程序正常運行。

在BMP中,鎖定到一個CPU的應用程序無法使用其他CPU,即使它們處於空閒狀態。 但是,QNX Neutrino RTOS允許您動態更改指定的CPU,而無需檢查點,然後停止並重新啓動應用程序。

QNX Neutrino通過runmask支持硬處理器親和性的概念。 在runmask中設置的每個位表示線程可以運行的處理器。 默認情況下,線程的runmask設置爲all,允許它在任何處理器上運行。 值0x01將允許線程僅在第一個處理器上執行。

默認情況下,進程或線程的子進程不繼承runmask; 有一個單獨的繼承掩碼。

通過仔細使用這些掩模,系統設計者可以進一步優化系統的運行時性能(例如,通過將非實時過程降級到特定處理器)。但是,一般情況下,這不是必需的,因爲當優先級較高的線程準備就緒時,我們的實時調度程序將始終搶佔優先級較低的線程。 處理器鎖定可能只會影響緩存的效率,因爲可以防止線程遷移。

您可以通過以下方式爲新線程或進程指定runmask:

  • 調用posix_spawnattr_setrunmask(),使用posix_spawnattr_setxflags()來設置
    POSIX_SPAWN_EXPLICIT_CPU擴展標誌,然後調用posix_spawn()

要麼:

  • 設置繼承結構的runmask成員並指定調用spawn()時SPAWN_EXPLICIT_CPU標誌。

要麼:

  • 啓動程序時,使用on或-ro選項啓用實用程序。 這也設定了流程將掩碼繼承到相同的值。

您可以通過以下方式更改現有線程或進程的運行掩碼:

  • 使用_NTO_TCTL_RUNMASK或_NTO_TCTL_RUNMASK_GET_AND_SET_ INHERIT命令對ThreadCtl()內核調用。

要麼:

  • 對slay實用程序使用-C或-R選項。如果還使用-i選項,則slay將繼承掩碼設置爲相同的值。

有關更多信息,請參閱QNX Neutrino程序員指南的多核處理章節。

A viable migration strategy

作爲AMP和SMP之間的中間點,如果您希望轉向完整的SMP,BMP提供了可行的遷移策略,但您擔心現有代碼可能在真正的併發執行模型中運行不正確。
您可以將遺留代碼移植到多核系統,並最初將其綁定到單個CPU以確保正確操作。 通過明智地將應用程序(可能還有單個線程)綁定到特定的CPU,您可以將潛在的併發問題隔離到應用程序和線程級別。 解決這些問題將允許應用程序完全同時運行,從而最大化多個處理器提供的性能增益。

Choosing between AMP, SMP, and BMP

AMP,SMP和BMP之間的選擇取決於您嘗試解決的問題:

  • AMP適用於傳統應用程序,但可擴展性超出兩個CPU。

  • SMP提供透明的資源管理,但尚未針對併發性設計的軟件可能存在問題。

  • BMP提供許多與SMP相同的優點,但保證單處理器應用程序將正常運行,極大地簡化了舊版軟件的遷移。

如下表所示,從任何這些模型中進行選擇的靈活性使您可以在性能,可伸縮性和遷移簡易性之間實現最佳平衡。

源文件:《Multicore Processing》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章