将 C 编译为 WebAssembly float returns 0?

Compiling C to WebAssembly float returns 0?

我做了一个简单的基准程序来测试 WebAssembly 代码和 javascript 之间的一些性能。问题是当调用我的导出函数时,我得到一个 0 值,而如果我使用 gcc 编译 C 程序,我会得到适当的输出。例如,4.843003

我刚刚开始 WebAssembly 编程,所以我不确定我做错了什么。当我 return 一个硬编码数字时,它似乎在我的 Chrome JS 控制台中工作正常。

我用来编译的标志:

 emcc -Os main.c -o main.wasm -s WASM=1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <emscripten.h>

int MAX_SIZE = 1000000;
int MAX_RUNS = 1000;

EMSCRIPTEN_KEEPALIVE
float benchmark() {
    int i, j;
    float seconds;
    clock_t t;
    int arr[MAX_SIZE];

    srand(time(0));

    t = clock();
    for(i = 0; i < MAX_RUNS; i++) {
        for(j = 0; j < MAX_SIZE; j++) {
            arr[j] = rand();
        }
    }
    t = clock() - t;

    seconds = ((float)t) / CLOCKS_PER_SEC;

    return seconds;
}

我想我不太确定在 JS 代码中,importObject 是干什么用的。我刚刚按照一些教程获得了某种输出,并通过查看 wasm2wat 输出得出了这个结论:

const importObject ={
    env: {
      STACKTOP: 0,
      STACK_MAX:65536,
      abortWhosebug: function(val) { throw new Error("stackoverfow"); },
      memory: new WebAssembly.Memory( { initial: 256, maximum:256 } ),
      table: new WebAssembly.Table( { initial:14, maximum:14, element: "anyfunc" } ),
      __memory_base:0,
      __table_base:0,
      _clock: () => {},
      abort: () => {},
      ___syscall146: () => {},
      _emscripten_memcpy_big: () => {},
      ___syscall6: () => {},
      ___syscall54: () => {},
      _time: () => {},
      ___syscall140: () => {},
      _printf: () => {},
      _rand: () => {},
      _srand: () => {},
      abortOnCannotGrowMemory: () => {},
      nullFunc_ii: () => {},
      nullFunc_iiii: () => {},
      nullFunc_jiji: () => {},
      ___lock: () => {},
      ___setErrNo: () => {},
      ___unlock: () => {},
      _emscripten_get_heap_size: () => {},
      _emscripten_memcpy_big: () => {},
      _emscripten_resize_heap: () => {},
      setTempRet0: () => {},
      tempDoublePtr: 0,
      DYNAMICTOP_PTR: 0
    }
};

WebAssembly.instantiateStreaming(fetch("main.wasm"), importObject).then((m) => {
    const { instance } = m;

    const n = instance.exports._benchmark();
    console.log(n);
});

所以我不确定这是否真的合适...关于我应该如何进行的任何想法?

clock()总是return0,因为_clock没有实现。

使用 emscripten 运行时。

emcc -Os main.c -o main.js -s WASM=1

或者自己定义,像这样

      _clock: () => { return Date.now() * 1000; },

正如@zakki 所说,你不应该 运行 .wasm 直接提交, 除非你知道它的意思。

WebAssembly 是一个非常小的 VM,它只能进行 运行 基本操作。它没有 any 系统库。它不知道 clock() 是什么意思,它没有任何文件系统,它不能 运行 TCP/IP 网络...它真的不能 any系统操作。

相反,Wasm 可以导入外部代码。在浏览器上下文中,Wasm 可以导入 JS 代码来模拟系统库。这就是 Emscripten 存在的原因。 Emscripten 不仅是一个 C/C++ -> Wasm 编译器,而且是一个完整的工具链,包括必要的 JS 运行时间来模拟 C 标准库 (libc)。

在你的例子中,你可以看到 time() 如何在 JS 端模拟 Emscripten source code:

clock: function() {
    if (_clock.start === undefined) _clock.start = Date.now();
    return ((Date.now() - _clock.start) * ({{{ cDefine('CLOCKS_PER_SEC') }}} / 1000))|0;
  }

所以基本上是借用JS的Date.now()函数来模拟的。 因此你不能 运行 .wasm 直接文件,你应该 运行 在 Emscripten JS 运行 的时候。

emcc -Os main.c -o main.js -s WASM=1

或者你可以在 HTML 和 运行 中完成。

emcc -Os main.c -o main.html -s WASM=1