可移植性(Portability):應用程序代碼需要能夠在所有設備使用的那些完全不同的Android 硬體上執行。
性能(Performance):上述的可移植性的限制範圍內,追求更多的性能。
可用性(Usability):簡化開發人員開發程式過程。
簡單來講,RS不需要像NDK一樣的複雜就可以寫出擁有比Java還要好的性能程式。
RenderScript是Android系統上的一種腳本(Script)語言,也就是說撰寫程式時除了Java部分外,還要寫一個附檔名為 rs 的腳本。在編譯上,我們所熟知Java部分會透過Java Compiler編譯成ByteCode,然後透過Dex Compiler編譯成Dalvik可執行的dex檔,而rs檔則透過 llvm-rs-cc Compiler一方面編譯成bc檔案與前面所述之dex檔合併於apk檔;另一方面則產生java程式碼的結構中產生相對應的 object。
(出處)
上述內容中所敘述的 llvm-rs-cc編譯器是基於LLVM編譯器,也因為採用了LLVM(Low Level Virtual Machine)編譯器的關係等於增加了異質多核心的平行運算功能。
因此,Google 在發佈Android 4.2的時候同時在Renderscript Computation中說明了支援GPU 運算的功能。(見Renderscript Computation說明)
一般RenderScript (以下簡稱RS) 大多是用來圖形處理,本文主要實作一個簡單的a+b的範例來完成Renderscript 平行運算。
開發環境:
Windows 8.1 64bit
Android 4.x版以上手機/平板或模擬器
Eclipse 3.7.2 + ADT 22.3.0
須注意的地方Android SDK Build-tools目前建議用18.0.1以下,因為18.0.1以上在編譯RS程式後會遇到很多設備無法執行的情況出現,待新版改善此問題後再使用新版的Build-tools。(見下圖)
建立專案:
程式內容:
由於輸出以Logcat為主,所以只要改Java及增加一個add.rs檔案,其他按照預設即可。
MainActivity.java內容:
package edu.nkut.hellorenderscript;
import android.app.Activity;
import android.os.Bundle;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.util.Log;
public class MainActivity extends Activity {
private RenderScript mRS;
private Allocation DataOut;
private ScriptC_add mScript;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
createScript();
}
private void createScript() {
mRS = RenderScript.create(this);
int RNGE = 10;
ScriptField_MyDataIn mIn = new ScriptField_MyDataIn(mRS, RNGE);
// 定義RS輸入資料
for (int i = 0; i < RNGE; ++i) {
mIn.set_a(i, i, false);
mIn.set_b(i, i*2, false);
}
mIn.copyAll();
DataOut = Allocation.createSized(mRS, Element.I32(mRS), RNGE);
// 呼叫 renderscript
mScript = new ScriptC_add(mRS, getResources(), R.raw.add);
mScript.forEach_root(mIn.getAllocation(), DataOut);
// 輸出結果
int[] Out = new int[RNGE];
DataOut.copyTo(Out);
for (int i = 0; i < RNGE; ++i) {
Log.i("MyParallel", "(a,b,sum)=("+mIn.get_a(i)+"+"+mIn.get_b(i)+"="+Out[i]+")");
}
}
}
程式說明:
31~35行定義了RS輸入的資料
40行定義了要執行的RS檔案,其中 ScriptC_add以及 R.raw.add 兩處的 add要跟 rs檔名一樣。
41行定義了使用forEach_root執行RS的平行運算。
add.rs檔案內容:
#pragma version(1)
#pragma rs java_package_name(edu.nkut.hellorenderscript)
struct MyDataIn {
int a;
int b;
};
void root(const struct MyDataIn *m_in, int *m_out) {
*m_out = m_in->a + m_in->b;
rsDebug("RS a=", (int) m_in->a);
rsDebug("RS b=", (int) m_in->b);
}
程式說明:
1行宣告了腳本使用的RenderScript版本。
2行宣告了腳本的Java package name。(注意這個地方要與Java檔案第一行的Package名稱一樣)
4~7行定義了RS輸入的資料
11行執行了a+b動作
13~14行rsDebug是RS輸出資訊到Logcat
對應到本文第一張圖內容,
ScriptC_add.java編譯後會出現在 gen目錄內。內容定義的類別可以讓程式呼叫腳本函式。
add.bc編譯後會出現在 bin/res/bc/raw目錄內。這就是LLVM編譯出來的檔案。
add.d編譯後會出現在 bin/rsDeps目錄內。列出add.bc檔案相依關係。
rs檔案要怎麼加入呢?
回覆刪除我新增一個婦檔名為.rs的檔案
不過卻顯示錯誤
可以放在src或jni的目錄
刪除意思是不管怎樣,這個專案都需要有c++的支持吧?
回覆刪除Java也行喔!
刪除