2016-02-04 25 views
1

我正在開發low level routines for binary search in C和x64程序集,並嘗試測量未緩存陣列(RAM中的數據)搜索的確切執行時間。根據分支預測的「幸運」程度,搜索同一個陣列以獲得不同的目標會花費大量不同的時間。我可以準確地測量最短執行時間和中間執行時間,但我發現很難衡量最大執行時間。用RDTSC精確測量最大週期數

問題是分支預測的最壞情況在時間上可以與平均情況加上處理器中斷相比較。最糟糕的情況和中斷都很少見,但我還沒有想出一個很好的方法來區分一個罕見事件和另一個罕見事件。標準方法是簡單地過濾掉所有「異常」的高測量值,但只有在兩者之間有清晰的線條時才能使用。

所以現在的問題變成,「我怎樣才能被中斷的測量和一個合法花更長的時間比其他地區之間的區別?

或者更一般地說,「如何衡量全執行時間的分佈,而不會事先假設一個硬性最大值?

內核是否存儲我可以查詢是否發生中斷的任何信息?在測量之前和之後我可以查詢哪些信息,這些信息會告訴我測量是否被中斷?理想情況下,它會告訴我中斷髮生的週期有多長,但只知道測量受到影響將是一個很好的開始。

也許除了(或不是)RDTSC之外,我可以使用RDPMC讀取一個計數器來測量Ring 0(內核)而不是Ring 3(用戶)所花費的週期數?是否有可能已經設立了櫃檯來做到這一點,或者我需要建立自己的櫃檯?我是否需要創建自己的內核模塊來執行此操作,還是可以使用現有的ioctls?

一些背景資料:

我運行主要是在英特爾SKYLAKE微架構i7-6700運行Ubuntu Linux的14.03 4.2.0,但我還測試了英特爾的Sandy Bridge和Haswell的。我已盡最大努力盡可能減少系統抖動。我已經使用CONFIG_NOHZ_FULL重新編譯了一個無tickless內核,沒有強制搶佔,支持透明的巨大頁面支持,並且定時器頻率爲100 Hz。

我停止了大部分不必要的進程,並刪除了大部分不必要的內核模塊。我使用cpuset/cset shield來爲單個進程保留一個NoHZ內核,並使用內核/調試/跟蹤來驗證我得到的中斷很少。但我仍然剛剛夠準確的測量是困難的。也許更重要的是,我可以設想未來的長尾情況(一個很少需要調整大小的散列表),它能夠區分有效和無效的測量將是非常有幫助的

我正在測量執行時間與RDTSC/RDTSCP使用Intel suggests in their whitepaper的技術,並且通常會獲得我期望的精度。我的測試涉及到搜索16位值,並且我在可變長度的隨機數組上重複單獨計時65536次搜索。爲了防止處理器學習正確的分支預測,每次都以不同的順序重複搜索。每次使用「CLFLUSH」搜索後,搜索的數組將從緩存中刪除。

這是一個研究項目,我的目標是瞭解這些問題。因此,我願意接近那可能被認爲是愚蠢和極端的事情。定製內核模塊,保護模式x64程序集,未經測試的內核修改以及處理器特定的功能都是公平的遊戲。如果有辦法擺脫少數剩餘的中斷,以便所有的測量都是「真實的」,那麼這也可能是一個可行的解決方案。感謝您的建議!

+0

我不能說出你的問題是什麼。所有的細節都沒有增加清晰度。 – Jeff

+0

嗨傑夫 - 對不起,如果我沒有清晰。問題是粗體的兩部分。我正在尋找一種方法來追溯確定在RDTSC測量期間處理器是否被中斷。對於後臺,考慮這個線程:https://software.intel.com/en-us/forums/software-tuning-performance-optimization-platform-monitoring/topic/405642其中帕特里克說:「請注意,在ring3(用戶土地),你也可能會在你的代碼中間出現中斷,這可能會讓你的計數變得糟糕。「我想弄清楚如何確定發生的時間。 –

+0

你可以禁用中斷嗎? – Jeff

回答

1

我假設你已經屏蔽你的標杆線程 儘可能:

  • 它已經到了CPU 核心獨佔訪問(不僅超線程),請參閱如何管理這一點很容易here
  • 中斷的親和性已從該內核移開,請參見here
  • 如果可能,請運行nohz內核以最小化計時器滴答聲。

此外,你不應該跳進內核空間從 基準比較的代碼路徑中:在返回時,你的線程可能會定 離開一段時間。

但是,你根本無法在CPU內核去掉所有的中斷:在 Linux中,本地APIC計時器中斷,處理器間中斷 (IPI)和其他用於內部的目的,你根本無法 擺脫他們!例如,定時器中斷用於確保線程最終被調度。同樣,IPI被用於在其他核心上執行觸發操作,例如TLB射擊。

現在,由於Linux跟蹤基礎設施的原因,可以從用戶空間中分辨出在某段時間內是否發生了一個 hardirq。

一個輕微的併發症是Linux的對待兩類中斷 不同方面的追查:

  1. 首先出現的是「真正的」外部硬件中斷,如網絡適配器,聲卡和 實際設備佔用這樣的。
  2. Linux有內部使用的中斷。

兩者都是在這個意義上,所述處理器異步 將控制轉移到所指示由 中斷描述符表(IDT)的中斷服務例程(ISR)hardirqs。

通常,在Linux中,ISR是簡單地用匯編存根其中 將控制轉移到寫入C.

對於細節的高級中斷處理程序,參照arch/x86/entry_entry_64.S在Linux內核源代碼。 對於Linux內部中斷,每個 都定義一個跟蹤存根,而對於外部中斷,跟蹤將留給高級別的中斷處理程序 。

這方法有每個內部中斷一個跟蹤事件:

# sudo perf list | grep irq_vectors: 
    irq_vectors:call_function_entry     [Tracepoint event] 
    irq_vectors:call_function_exit      [Tracepoint event] 
    irq_vectors:call_function_single_entry    [Tracepoint event] 
    irq_vectors:call_function_single_exit    [Tracepoint event] 
    irq_vectors:deferred_error_apic_entry    [Tracepoint event] 
    irq_vectors:deferred_error_apic_exit    [Tracepoint event] 
    irq_vectors:error_apic_entry      [Tracepoint event] 
    irq_vectors:error_apic_exit      [Tracepoint event] 
    irq_vectors:irq_work_entry       [Tracepoint event] 
    irq_vectors:irq_work_exit       [Tracepoint event] 
    irq_vectors:local_timer_entry      [Tracepoint event] 
    irq_vectors:local_timer_exit      [Tracepoint event] 
    irq_vectors:reschedule_entry      [Tracepoint event] 
    irq_vectors:reschedule_exit      [Tracepoint event] 
    irq_vectors:spurious_apic_entry     [Tracepoint event] 
    irq_vectors:spurious_apic_exit      [Tracepoint event] 
    irq_vectors:thermal_apic_entry      [Tracepoint event] 
    irq_vectors:thermal_apic_exit      [Tracepoint event] 
    irq_vectors:threshold_apic_entry     [Tracepoint event] 
    irq_vectors:threshold_apic_exit     [Tracepoint event] 
    irq_vectors:x86_platform_ipi_entry     [Tracepoint event] 
    irq_vectors:x86_platform_ipi_exit     [Tracepoint event] 

,而只存在於外部中斷一個總的跟蹤事件:

# sudo perf list | grep irq: 
    irq:irq_handler_entry        [Tracepoint event] 
    irq:irq_handler_exit        [Tracepoint event] 
    irq:softirq_entry         [Tracepoint event] 
    irq:softirq_exit         [Tracepoint event] 
    irq:softirq_raise         [Tracepoint event] 

因此,跟蹤所有這些IRQ *_entries您的基準測試代碼路徑的持續時間,您知道您的基準示例是否已被中毒請求中毒 。

請注意,x86上有第三種硬件中斷樣式: 例外。至少,我也會檢查頁面錯誤。 並且對於以上錯過的NMI(通過nmi:nmi_handler)。

爲了您的方便,我在 的基準代碼路徑中對IRQ進行了跟蹤,我已經編制了little piece of code。有關 的用法,請參閱包含的example.c。請注意,需要訪問/sys/kernel/debug以便 確定跟蹤點ID。

+0

謝謝,我認爲這是一個非常有前途的方向。是的,我認爲我已經完成了所有建議以減少中斷,目標是檢測剩餘的幾個。我一直在閱讀關於dtrace接口的大量內容,但沒有見過這樣的例子perf_event。我會玩你的代碼,然後更全面地迴應。我認爲這種方法可能對我很有效,只需稍加修改即可覆蓋1赫茲hrtimer內務管理活動,如Frederic展示:https://kernel.googlesource.com/pub/scm/linux/kernel/git/frederic/dynticks-testing /+/master/trace.1.example –

+0

如果我的代碼尚未覆蓋時間片,只需將'timer:hrtimer_expire_entry'添加到'lxdetectirq.h'中的'event_names'列表。 –

+0

'timer/hrtimer_expire_entry',當然這些是文件名。 –