将C编译为WebAssembly float返回0?

时间:2019-07-24 00:53:55

标签: webassembly

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

我只是刚开始进行WebAssembly编程,所以我不确定自己做错了什么。当我返回一个硬编码的数字时,它似乎可以在我的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;
}

我想我不太确定importObject是什么在JS代码中。我刚刚按照一些教程来获取某种输出,并通过查看wasm2wat输出来提出:

const importObject ={
    env: {
      STACKTOP: 0,
      STACK_MAX:65536,
      abortStackOverflow: 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);
});

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

2 个答案:

答案 0 :(得分:1)

如@zakki所说,除非您知道它的含义,否则不应该直接运行.wasm文件

WebAssembly是真正的最小VM,仅能够运行基本操作。它没有任何系统库。它不知道clock()是什么意思,它没有任何文件系统,并且不能运行TCP / IP网络...它确实不能执行任何系统操作。

相反,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

答案 1 :(得分:0)

clock()始终返回0,因为未实现_clock

使用emscripten运行时。

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

或者像这样自己定义它们

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