gpt4 book ai didi

javascript - 如何将 ArrayBuffer 从 JS 传递到 AssemblyScript/Wasm?

转载 作者:搜寻专家 更新时间:2023-10-30 20:56:59 36 4
gpt4 key购买 nike

我有一段非常简单的 Typescript 代码来解析特定的数据格式,输入是一个 UInt8Array。我已经尽可能地优化了它,但我认为这个相当简单的解析器应该能够比我让它作为 JS 运行得更快。我想尝试使用 AssemblyScript 在 Web 程序集中编写它,以确保我不会遇到 Javascript 引擎的任何怪癖。

我现在明白了,我不能只将 TypedArray 传递给 Wasm 并让它自动工作。据我所知,我可以传递一个指向数组的指针,并且应该能够直接从 Wasm 访问它而无需复制数组。但我无法让它与 AssemblyScript 一起工作。

以下是一个最小示例,展示了我如何无法将 ArrayBuffer 传递给 Wasm。

设置 Wasm 导出的代码主要来自自动生成的样板文件:

const fs = require("fs");
const compiled = new WebAssembly.Module(
fs.readFileSync(__dirname + "/build/optimized.wasm")
);
const imports = {
env: {
abort(msgPtr, filePtr, line, column) {
throw new Error(`index.ts: abort at [${line}:${column}]`);
}
}
};
Object.defineProperty(module, "exports", {
get: () => new WebAssembly.Instance(compiled, imports).exports
});

下面的代码调用了WASM,index.js是上面的胶水代码。

const m = require("./index.js");
const data = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
const result = m.parse(data.buffer);

编译成 WASM 的 AssemblyScript 如下:

import "allocator/arena";

export function parse(offset: usize): number {
return load<u8>(offset);
}

当我执行该代码时,出现“RuntimeError:内存访问越界”。

主要问题是我从 Wasm 返回的错误根本无法帮助我自己解决这个问题。我显然错过了这在幕后如何实际运作的一些主要方面。

我实际上如何使用 AssemblyScript 将 TypedArray 或 ArrayBuffer 从 JS 传递到 Wasm?

最佳答案

在 AssemblyScript 中,有多种方法可以从内存中读取数据。获取此数据的最快捷方式是在模块的函数导入中使用链接函数来返回指向数据本身的指针。

let myData = new Float64Array(100); // have some data in AssemblyScript

// We should specify the location of our linked function
@external("env", "sendFloat64Array")
declare function sendFloat64Array(pointer: usize, length: i32): void;

/**
* The underlying array buffer has a special property called `data` which
* points to the start of the memory.
*/
sendFloat64Data(myData.buffer.data, myData.length);

然后在 JavaScript 中,我们可以在链接函数中使用 Float64Array 构造函数直接返回值。

/**
* This is the fastest way to receive the data. Add a linked function like this.
*/
imports.env.sendFloat64Array = function sendFloat64Array(pointer, length) {
var data = new Float64Array(wasmmodule.memory.buffer, pointer, length);
};

但是,有一种更清晰的方法来获取数据,它涉及从 AssemblyScript 返回一个引用,然后使用 AssemblyScript 加载器。

let myData = new Float64Array(100); // have some data in AssemblyScript

export function getData(): Float64Array {
return myData;
}

然后在JavaScript中,我们可以使用AssemblyScript提供的ASUtil加载器。

import { instantiateStreaming } from "assemblyscript/lib/loader";

let wasm: ASUtil = await instantiateStreaming(fetch("myAssemblyScriptModule.wasm"), imports);

let dataReference: number = wasm.getData();
let data: Float64Array = wasm.getArray(Float64Array, dataReference);

出于代码清晰的原因,我强烈建议使用第二个示例,除非性能绝对至关重要。

祝您的 AssemblyScript 项目好运!

关于javascript - 如何将 ArrayBuffer 从 JS 传递到 AssemblyScript/Wasm?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54738197/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com