您好我是一個新手,並試圖代碼的renderScript計算數組中值的總和。我想知道如何使用渲染腳本在數組中執行元素的總和。有沒有一種方法可以將輸出傳遞迴腳本以進行順序添加?我的問題的說法是: 矢量和使用的renderScript
描述:計算數組中的值的總和。
輸入:整數數組
輸出:整數
任何幫助,將不勝感激!
您好我是一個新手,並試圖代碼的renderScript計算數組中值的總和。我想知道如何使用渲染腳本在數組中執行元素的總和。有沒有一種方法可以將輸出傳遞迴腳本以進行順序添加?我的問題的說法是: 矢量和使用的renderScript
描述:計算數組中的值的總和。
輸入:整數數組
輸出:整數
任何幫助,將不勝感激!
這恐怕是更復雜一點似乎比,但我會盡我所能解釋這裏,你可以採取實現這一可能的途徑。
你所要求的是並行簡化算法,它可以實現或者是你的情況下的數組求和,或者是任何其他交換+關聯運算符,當迭代應用到數組上時,它將「減少」它到一個單一的數字。其他示例是查找大數組的最大值或最小值。在CUDA和OpenCL中,這種計算有一個衆所周知的模式,它能夠最大限度地利用並行線程,例如,如果谷歌「CUDA減少」,您將獲得大量有用的信息。
,這是實現的途徑是通過反覆減少一半的陣列,一遍又一遍,直到你結束了一個單一的元素。每次減少它時,每個新元素都是前兩個元素的總和。下面是更好的描述了這個算法的圖片:
因此,例如,你以一個16個元素的數組。你只運行一次算法,最後得到一個8個元素的數組 - 這8個元素中的每一個都是來自原始數組的兩個數字的總和。
你再次運行它,你將得到4種元素 - 其中每一項都是兩個數字從上一步驟的總和。您的總和 - 等等......
你不停,直到你最終只有一個號碼這樣做。
中的renderScript實施,這將是的低效方式:
的Java:
int[] ints; // Your data is held here.
Allocation data = Allocation.createSized(rs, Element.I32(rs), ints.length, Allocation.USAGE_SCRIPT);
data.copy1DRangeFrom(0, ints.length, ints);
ScriptC_Reduce script = new ScriptC_Reduce(rs);
script.bind_data(data);
for (int stride = ints.length/2; stride > 0; stride /= 2) {
script.set_stride(stride);
script.forEach_root(input, output);
}
data.copyTo(ints);
int totalsum = ints[0];
的renderScript:
#pragma version(1)
#pragma rs java_package_name(...[your package here]...)
int stride;
int * data;
void root(const int32_t *v_in, int32_t *v_out, uint32_t x) {
if (x < stride) data[x] += data[x + stride];
}
如果你用RS工作過,你可能注意幾件奇怪的事情:
但是,我上面提到,這是一個效率低下的實現。但它應該指向正確的方向。爲了使效率更高,可能需要將數據拆分爲更小的塊,以便分別計算,因爲如此處所述,此算法將在每個迭代步驟運行ints.length線程數,並在非常大的數組上運行,這將導致批次的步驟,以及在每個步驟的空閒線程的批號。
此外,這假定你的數組的長度正好是2的冪,所以多重對分只會導致一個元素。對於其他大小的陣列,您可能需要填充陣列。再次,在處理非常大的數組時,0填充將需要大量浪費的內存。
因此,要解決這些問題,您可能需要將您的數組分成多個,例如每個64個元素。因此,如果你沒有一個確切的數組長度,填充「最後」塊到64將不需要那麼多的內存。此外,您將需要更少的迭代步驟(以及更少的空閒線程)來減少64個元素。當然,64是我剛剛製作的一個神奇數字。嘗試2的其他權力來查看他們的結果,您可能會看到更好的結果與其他塊大小,如16或32.我懷疑性能與塊大小將非常依賴硬件。
編輯:這假定RenderScript可以使用它的GPU上運行的設備驅動程序,以便它可以實際啓動大量的並行線程。否則,像這樣的僅執行CPU的內核可能會比處理數組lineary更慢。
不要。除非你有比1增加更奇特的東西。別。只有在該陣列中至少有400萬個整數時,代碼纔會更快。
RenderScript: Entries:1 Total: 3 Time: 0.067ms
Simple Loop : Entries:1 Total: 3 Time: 0.001ms
RenderScript: Entries:2 Total: 97 Time: 0.614ms
Simple Loop : Entries:2 Total: 97 Time: 0.001ms
RenderScript: Entries:4 Total: 227 Time: 0.28ms
Simple Loop : Entries:4 Total: 227 Time: 0.002ms
RenderScript: Entries:8 Total: 320 Time: 0.445ms
Simple Loop : Entries:8 Total: 320 Time: 0.002ms
RenderScript: Entries:16 Total: 700 Time: 0.486ms
Simple Loop : Entries:16 Total: 700 Time: 0.002ms
RenderScript: Entries:32 Total: 1807 Time: 0.595ms
Simple Loop : Entries:32 Total: 1807 Time: 0.002ms
RenderScript: Entries:64 Total: 3218 Time: 0.624ms
Simple Loop : Entries:64 Total: 3218 Time: 0.002ms
RenderScript: Entries:128 Total: 6230 Time: 0.737ms
Simple Loop : Entries:128 Total: 6230 Time: 0.003ms
RenderScript: Entries:256 Total: 12968 Time: 0.769ms
Simple Loop : Entries:256 Total: 12968 Time: 0.005ms
RenderScript: Entries:512 Total: 26253 Time: 0.895ms
Simple Loop : Entries:512 Total: 26253 Time: 0.01ms
RenderScript: Entries:1024 Total: 52345 Time: 0.987001ms
Simple Loop : Entries:1024 Total: 52345 Time: 0.017ms
RenderScript: Entries:2048 Total: 100223 Time: 1.715ms
Simple Loop : Entries:2048 Total: 100223 Time: 0.034ms
RenderScript: Entries:4096 Total: 200375 Time: 1.213ms
Simple Loop : Entries:4096 Total: 200375 Time: 0.065ms
RenderScript: Entries:8192 Total: 403713 Time: 1.196ms
Simple Loop : Entries:8192 Total: 403713 Time: 0.163001ms
RenderScript: Entries:16384 Total: 812411 Time: 1.929ms
Simple Loop : Entries:16384 Total: 812411 Time: 0.41ms
RenderScript: Entries:32768 Total: 1620542 Time: 1.822ms
Simple Loop : Entries:32768 Total: 1620542 Time: 0.617ms
RenderScript: Entries:65536 Total: 3250733 Time: 5.955ms
Simple Loop : Entries:65536 Total: 3250733 Time: 1.384ms
RenderScript: Entries:131072 Total: 6478866 Time: 2.622ms
Simple Loop : Entries:131072 Total: 6478866 Time: 2.008ms
RenderScript: Entries:262144 Total: 12980832 Time: 3.979999ms
Simple Loop : Entries:262144 Total: 12980832 Time: 4.377001ms
RenderScript: Entries:524288 Total: 25956676 Time: 10.163ms
Simple Loop : Entries:524288 Total: 25956676 Time: 8.326ms
RenderScript: Entries:1048576 Total: 51897168 Time: 12.723001ms
Simple Loop : Entries:1048576 Total: 51897168 Time: 15.871999ms
RenderScript: Entries:2097152 Total: 103867356 Time: 32.229001ms
Simple Loop : Entries:2097152 Total: 103867356 Time: 31.367ms
RenderScript: Entries:4194304 Total: 207646704 Time: 61.628999ms
Simple Loop : Entries:4194304 Total: 207646704 Time: 63.378ms
RenderScript: Entries:8388608 Total: 415058480 Time: 103.734999ms
Simple Loop : Entries:8388608 Total: 415058480 Time: 140.088ms
這是切割所有在renderscript的青睞。就像假設所有的分配將在主循環之外完成,並且不需要將數據陣列複製出去(我簡單地稱爲rs.finish()來確保渲染完成)。
#pragma version(1)
#pragma rs java_package_name(com.photoembroidery.tat.olsennoise)
int stride;
int * data;
void root(const int32_t *v_in, int32_t *v_out, uint32_t x) {
data[x] += data[x + stride];
}
請注意啓動選項。你做第一次裁減,將數組調整到正確的2倍。因此,你可以在之前的大小和兩個因子之間採取任何餘數,然後處理這些條目,這樣它們就會以2的因子減少。然後你處理兩個因素。
//int[] array = //array of your data//;
ScriptC_reduce script = new ScriptC_reduce(mRS);
Allocation data = Allocation.createSized(mRS, Element.I32(mRS), array.length, Allocation.USAGE_SCRIPT);
data.copy1DRangeFrom(0, array.length, array);
script.bind_data(data);
int smallest2ExpBiggerThanLength = 1;
for (int length = arraysize; length != 0; length >>= 1,smallest2ExpBiggerThanLength <<= 1);
int end = smallest2ExpBiggerThanLength/2;
int start = smallest2ExpBiggerThanLength - arraysize;
if (start == end) {
start = 0;
end = end/2;
}
while (end > 0) {
launchOptions.setX(start, end);
script.set_stride(end - start);
script.forEach_root(data, data, launchOptions);
script.forEach_root(data,data);
end = end >> 1;
start = 0;
}
data.copyTo(array);
int total = array[0];
其他答案中最大的低效率是啓動選項。從限制範圍開始,而不是檢查範圍的有效性,你會更好。你輸了4倍的速度。一個簡單的循環將會更快更通用,而不會引發渲染錯誤。 - 你需要做一些比1增加更難的事情。
我們實際上正在努力支持「reduce」作爲下一個Android版本的新內核類型。這將允許您在分配的單元格上運行關聯操作(如添加),並獲得單個減少的結果。代碼已經存在於AOSP中,但我們正試圖使其更靈活/一般。當前窗體已經允許你指定一個2輸入 - > 1輸出內核,它可以應用於所有單元。在此期間,您可以通過在可調參數中依次運行並使用rsGetElementAt _ *()來遍歷單元格來近似減少內核。這比Java要快得多,在這種情況下你不斷付出不必要的邊界檢查(以及其他開銷)。
這種方法應該適用於非常大的數組。對於更小的陣列,數以千計的元素,簡單的循環可能會更快。 –
看完這篇文章後我有點困惑。您將方法「root」稱爲內核,但是從Android文檔中可以看出內核具有標識符__attribute __((kernel)),因此這是一個可調用的函數。因此它是一個單線程函數。我錯過了什麼嗎? – eldjon
'root(...)'是RenderScript文件中一個特殊的保留方法名稱,它始終充當該類的主要內核。雖然可以像上面提到的那樣通過用內核屬性指定內核屬性來將_additional_內核添加到同一個類中,但內核始終是「默認」內核。然後,從java端,它被稱爲'script.forEach_root(...)'。 – monoeci