通过引用从 JS 传递数组以供 WASM 编辑?

Posted

技术标签:

【中文标题】通过引用从 JS 传递数组以供 WASM 编辑?【英文标题】:Pass arrays from JS by reference for WASM to edit? 【发布时间】:2020-01-15 19:06:25 【问题描述】:

在 AssemblyScript 中传递和返回浮点数组的最佳方式是什么?

我可以传递一个数组形式 JS(通过引用)供 WASM 编辑吗?

export function nBodyForces(data: f64[], result: f64[]): void 

以下是我现在所拥有的。忽略实现细节,它会返回 2000,然后将其增加到 8000ish。

返回一组新值的最佳方法是什么?

export function nBodyForces(data: f64[]): f64[] 
  // Each body has x,y,z,m passed in.
  if (data.length % bodySize !== 0) return new Array<f64>(10);
  const numBodies: i32 = data.length / bodySize;

  // return a 3-force x,y,z vector for each body
  let ret: f64[] = new Array<f64>(numBodies * forceSize);  

  /**
   * Calculate the 3-vector each unique pair of bodies applies to each other.
   * 
   *   0 1 2 3 4 5
   * 0   x x x x x
   * 1     x x x x
   * 2       x x x
   * 3         x x
   * 4           x
   * 5
   * 
   * Sum those forces together into an array of 3-vector x,y,z forces
   */

  // For all bodies:
  for (let i: i32 = 0; i < numBodies; i++) 
    // Given body i: pair with every body[j] where j > i
    for (let j: i32 = i + 1; i < numBodies; j++) 
      // Calculate the force the bodies apply to one another
      const bI: i32 = i * 4
      const bJ: i32 = j * 4
      let f: f64[] = twoBodyForces(
        // b0
        data[bI], data[bI+1], data[bI+2], data[bI+3], // x,y,z,m
        // b1
        data[bJ], data[bJ+1], data[bJ+2], data[bJ+3], // x,y,z,m
      );
      // Add this pair's force on one another to their total forces applied x,y,z
      // body0
      ret[bI] = ret[bI] + f[0];    
      ret[bI+1] = ret[bI+1] + f[1];    
      ret[bI+2] = ret[bI+2] + f[2];
      // body1    
      ret[bJ] = ret[bJ] + f[0];    
      ret[bJ+1] = ret[bJ+1] + f[1];    
      ret[bJ+2] = ret[bJ+2] + f[2];
    
  
  // For each body, return the summ of forces all other bodies applied to it.
  return ret;


【问题讨论】:

【参考方案1】:

为了与 JS 更快的互操作,我建议尽可能使用类型化数组

export const FLOAT64ARRAY_ID = idof<Float64Array>();
export function nBodyForces(data: Float64Array): Float64Array  ... 

稍后在 javascript 方面:

const loader = require("assemblyscript/lib/loader");
const imports = ;
const wasm = await loader.instantiateStreaming(fetch("optimized.wasm"), imports);

const dataArray = [... your data ...]
const dataRef = wasm.__retain(wasm.__allocArray(wasm.FLOAT64ARRAY_ID, dataArray));

const resultRef = wasm.nBodyForces(dataRef);
const resultArray = wasm.__getFloat64Array(resultRef);

// release ARC resources
wasm.__release(dataRef);
wasm.__release(resultRef);

console.log("result: " + resultArray);

【讨论】:

好的,很有趣。看起来这是内存的分配/复制/释放。有没有办法用共享线性内存做到这一点?我正在尝试去 DomThread -> WebWorker -> Wasm -> 并返回。 在 Chrome 和 FF 中,我得到“wasm.__allocArray”不是一个函数。我尝试了运行时完整和一半(和默认)。我正在使用 WebAssembly.instantiate(msg.wasmModule, importObj) 在 web worker 中实例化 wasm。 你应该使用“assemblyscript/lib/loader”而不是WebAssembly.instantiate。加载程序暴露__allocArray__retain__release 等,还包装了instantiateStreaming/instantiate。请参阅我的示例中的第一行 我看到了。没有 require() 和 webpack 就没有解决方案吗? 你可以试试这样的: 但我推荐使用 webpack 或 rollup

以上是关于通过引用从 JS 传递数组以供 WASM 编辑?的主要内容,如果未能解决你的问题,请参考以下文章

JS不能向WASM传递数组?

C++ 通过引用传递数组

wasm与js,输入输出

C ++通过引用其他类传递二维数组

如何通过引用从 c# 到 c++ 传递字节数组

thinkphp js参数传递问题