數據預取 __builtin_prefetch()


__builtin_prefetch() 是 gcc 的一個內置函數。它通過對數據手工預取的方法,減少了讀取延遲,從而提高了性能,但該函數也需要 CPU 的支持。

該函數的原型為:

void __builtin_prefetch (const void *addr, ...)



其中參數 addr 是個內存指針,它指向要預取的數據,我們人工需要判定這些數據是很快能訪問到的,或者說是它們就在最近的內存中 --- 一般來說,對於鏈表而言,各個節點在內存中基本上是緊挨着的,所以我們容易預取鏈表節點里的指針項。

該函數還有兩個可選參數,rw 和 locality 。

rw 是個編譯時的常數,或 1 或 0 。1 時表示寫(w),0 時表示讀(r) 。

locality 必須是編譯時的常數,也稱為“時間局部性”(temporal locality) 。時間局部性是指,如果程序中某一條指令一旦執行,則不久之后該指令可能再被執行;如果某數據被訪問,則不久之后該數據會被再次訪問。該值的范圍在 0 - 3 之間。為 0 時表示,它沒有時間局部性,也就是說,要訪問的數據或地址被訪問之后的不長的時間里不會再被訪問;為 3 時表示,被訪問的數據或地址具有高 時間局部性,也就是說,在被訪問不久之后非常有可能再次訪問;對於值 1 和 2,則分別表示具有低 時間局部性 和中等 時間局部性。該值默認為 3 。

用法:

for (i = 0; i < n; i++)
            {
              a[i] = a[i] + b[i];
              __builtin_prefetch (&a[i+j], 1, 1);
              __builtin_prefetch (&b[i+j], 0, 1);
              /* ... */
            }



另外,參數 addr 是需要用戶保證地址的正確,函數不會對不正確的地址做出錯誤的提示。

在 linux 內核中,經常會使用到這種預抓取技術。通常是通過宏和包裝器函數使用預抓取。下面是一個輔助函數示例,它使用內置函數的包裝器(見 ./linux/include/linux/prefetch.h)。這個函數為流操作實現預抓取機制。使用這個函數通常可以減少緩存缺失和停頓,從而 提高性能。

#ifndef ARCH_HAS_PREFETCH
#define prefetch(x) __builtin_prefetch(x)
#endif

static inline void prefetch_range(void *addr, size_t len)
{
#ifdef ARCH_HAS_PREFETCH
    char *cp;
    char *end = addr + len;

    for (cp = addr; cp < end; cp += PREFETCH_STRIDE)
        prefetch(cp);
#endif
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM