2016-06-16 9 views
2

私はEmscripten C++ Web Workerを使用していますが、大規模なデータをJavaScriptプログラムに転送する方が効率的です。Emscripten C++ Webワーカーを使用した大規模配列の効率的な転送:どのJavaScriptの設計が優れていますか?

Webワーカーがclone()を実行してシリアル化しているため、Webワーカーメッセージシステムを介して転送するために、ここにオーバーヘッドがあります。また、C++側の結果データをHEAP32からJavaScript配列(C -> JS)に変換するには、いくつかのコードが必要です。

効率的とは、どのデザインが高速であるか、つまりどのデザインがトリガーになるかをnewgc()(JSオブジェクトの作成と破棄)につなげることを意味します。私のWebワーカーは、大きな配列(float[V][3]int[N][3]とN = V = 10000の2つの配列を返すC++で書かれたコア関数を使用して、ThreeJSジオメトリを更新するために使用され、数万倍Webページ上の長い期間。別にスローされ、これはまた、ブラウザは、遅くフリーズまたはクラッシュすることがあります。

  1. は、JSコードがEmscriptenを使用してコンパイルインポートJSを使用してWebワーカーを書く。短所をコンパイルJSファイルをインポートする必要があるため、このオプションは不可能です。データ交換:C++ -> JS -> message(serialise) -> JSデザイン:(C++)JS <-WW-> JSファイル:core_mc_algorithm.cpp、worker.js、main.js。
  2. -s BUILD_AS_WORKER=1を使用してコンパイルされたC++ Webワーカーを使用して、データを受け取ったメイン側に他のC++コードを書き、メイン側のHEAPからJSへの結果を変換します(Emscriptenによって処理されるWebWorkerデータtraser):Pros:効率的な転送ですが、2回のコンバージョンが必要です。 リスク:C++側では、ベクトルから配列などへの複数のコピーが必要です。データ交換:C++ -> message(serialise) -> C++ -> JS、デザイン:(C++) <-WW-> C++(JS)ファイル:worker.cpp、main.cpp、main.js。
  3. また、C++ Webワーカーでも、Webワーカー関数にはJavaScriptのメインプログラムが直接連絡します。 長所:コンバージョン/交換は2回行われません。 C++とJSの間には別の交換はありません。この変換はWW直列化と同時に行われます。 リスク:デコードが難しくて面倒かもしれません(プロトコルを再実装する必要があります。それ自体は複数回の変換が必要ですが、それほど効率的ではありません)。また、交換は実際には効率的でない可能性があり、実際にはパフォーマンスを向上させることはできません。 データ交換:C++ -> message(serialise) -> JS、デザイン:(C++) <-WW-> JSファイル:worker.cpp、main.js。

私は私がWebワーカーとして、それを実行したい、C++でこのコードを持っている:

void produce_object (
    REAL* verts_output, int number_of_vertices, 
    int* faces_output, int number_of_triangles) { 
    // Run Marching cubes, which produces a vector<int> and a vector<float>. 
    // fills in the arrays verts_output[] with coordinates (size: 3*number_of_vertices), 
    // fill in faces_output[] with triangle vertex indices (size: 3*number_of_triangles), using some numerical code which includes the Marching Cubes algorithm. 
} 

私は右のパラメータで呼び出されますし、次のJavaScriptのコールバック関数が必要です。これは、HTMLファイルで定義されています

function update_mesh_geometry_callback (verts, faces) { 
    /* verts and faces are of type Float32Array and Int32Array of size (3*N) and (3*V). In this function they are used to create the following object, which is added to the scene.*/ 
    var geo = new THREE.Geometry(verts, faces); // a subclass 
    scene.add(new THREE.Mesh(gro, mat, etc)); 
} 

典型的なサイズ、少なくとも:number_of_vertices == 90000 = N、number_of_trianglesの== 8000 = V.

+1

はTypedArrayの形式であなたのそれらの配列はありますか? javascript TypedArrayの実装には、コピーする代わりに転送できるバイトストリームが含まれているためです。 –

+0

効率のためのいくつかのルール:1)メモリの再割り当てを控える。メモリバッファを再利用する。 2)データ転送時のデータサイズを最大化する。 3)プロセッサデータキャッシュの最適な使用のための設計およびコード。 –

+0

@SohailSiあなたの質問は、意味のある答えを得るための十分な情報がないと思います。どのデータを転送するのかを絞り込み、どのように生成しますか。 –

答えて

1

私はあなたがtransferablesの後にあると信じています。労働者はpostMessage方法で追加のパラメータがあります。 はhttps://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage

TransferablesだけArrayBuffer秒で作業を、彼らはまた、解除バッファ・メッセージング・スレッドから、あなたは心の中でそれを維持する必要がありますが、あなたのケースのために、これはそれのように完璧にフィットのように思えます完全にコピーを避けるでしょう。あなたの労働者に

var vertices = new Float32Array(100000); 
var faceIndices = new Uint32Array(50000); 
postMessage({vertices: vertices, faceIndices: faceIndices}, [vertices.buffer, faceIndices.buffer]); 

を持っているだろうかあなたがここにtransferrablesの詳細を読むことができるため、ここで

は、おもちゃのコードの例です: Using transferable objects from a Web Worker

+1

"完全にコピーしないようにする" ... Emscriptenで管理されたヒープに/からアイテムを送信する場合には、これが正しいとは思わない。 –

+0

私たちがワーカーインターフェースについて話すなら、それはゼロコピーですが、あなたが指摘したように、データはemscriptenのコンテキストから取得する必要があります。しかし、あなたはまだRAMからL3、L2、L1、レジスタ、それを避ける方法に関する提案、@MichalCharemzaにコピーされたデータで終わるだろうか? – travnik

+0

私の知るところではない恐怖...私はプロセッサ(/中間のキャッシュ)を経由せずにあるRAMの場所から別のRAMの場所にメモリをコピーすることが可能かどうか疑問に思っています。 –