2012-10-20 109 views
1

我對圖像的子區域進行了大量操作。例如,如果我有一個100x100的圖像,我可能想迭代這個圖像並處理10x10像素的塊。例如:顯式預取非連續數據

for(each 10x10 block) 
{ 
    for(each pixel in the block) 
    { 
    do something 
    } 
} 

這種方法的問題是,小塊不是連續的內存塊(即,圖像的像素被存儲以行優先順序,所以,當我訪問10×10塊,每行中的像素的塊是連續的,但塊的行不是連續的,有什麼可以做的,以加速訪問這些塊中的像素?或者是不可能快速訪問數據的一個區域像這樣的結構?

從我讀過的很多讀物中,聽起來像是第一次讀取像素,因爲循環中唯一的操作可能是有用的:

// First read the pixels 
vector<float> vals(numPixels); 
for(pixels in first row) 
{ 
val[i] = pixels[i]; 
} 

// Then do the operations on the pixels 
for(elements of vals) 
{ 
doSomething(vals[i]) 
} 

與我在做什麼這是兩者同時進行公正:

// Read and operate on the pixels 
for(pixels in first row) 
{ 
doSomething(pixels[i]) 
} 

,但我無法找到任何實際的代碼示例(與理論解釋)是如何做到這一點。有沒有道理呢?

+0

將像素複製到矢量中會將它們放入連續的內存區域,如果它們適合高速緩存線,則通常會對其進行高速緩存。 – chradcliffe

+0

@chradcliffe,但如果他們只使用一次會幫助什麼? –

+0

我認爲@MvG對此有正確答案。 '__builtin_prefetch'將是正確的使用。我已經忘記了那個內建。它將保存副本並在您僅使用一次值的情況下工作。 – chradcliffe

回答

1

gcc有一個內建功能__builtin_prefetch。您可以將地址傳遞給該函數,並且在支持該函數的目標上,gcc將發出機器指令,使該地址即使未立即使用,也會將其加載到緩存中。

許多現代圖像處理應用商店圖像瓷磚,而不是在(又名*掃描線)你描述。例如。 GIMP does that。因此,如果您可以控制圖像的存儲方式,那麼使用平鋪方法可能會增加局部性,從而減少緩存未命中並提高性能。

+0

使用掃描線存儲系統時,是否必須預取小圖像塊的每個地址?或者只是行塊中每行的第一個像素的地址? –

+0

@DavidDoria,每當你預取一個字節的數據,它的整個緩存行將被加載到緩存中。與圖像相關的方式取決於CPU架構,內存對齊等。一般來說,我會假設爲每一行預加載第一個像素*就足夠了。如果有疑問,請嘗試兩種方法並對其進行基準測試 – MvG