在Worker中使用Emscripten(wasm)

先在c文件中创建一个用于并发执行的方法:

#ifndef EM_PORT_API
#if defined(__EMSCRIPTEN__)
#include <emscripten.h>
#if defined(__cplusplus)
#define EM_PORT_API(rettype) extern "C" rettype EMSCRIPTEN_KEEPALIVE
#else
#define EM_PORT_API(rettype) rettype EMSCRIPTEN_KEEPALIVE
#endif
#else
#if defined(__cplusplus)
#define EM_PORT_API(rettype) extern "C" rettype
#else
#define EM_PORT_API(rettype) rettype
#endif
#endif
#endif
#include <stdio.h>
double Random()
{
	static int seed = 1;
	static int const a = 16807, m = 2147483647, q = 127773, r = 2836;

	seed = a * (seed % q) - r * (seed / q);
	if (seed < 0) seed += m;
	return (double)seed / (double)m;
}

EM_PORT_API(double) Pi(int trials)
{
	double sum = 0.0;
	for (int j = 0; j < 100; j++)
	{
		int hits = 0;
		for (int i = 0; i < trials; i++)
		{
			double x = Random();
			double y = Random();
			if (x * x + y * y < 1.0)
				hits++;
		}
		sum += 4.0 * hits / trials;
		printf("Worker: Pi() round %d.\n", j + 1);
	}
	return sum / 100.0f;
}

这里创建了一个计算圆周率的方法Pi()。

在编译之前,额外准备一个pre.js文件(该文件将被插入到 emcc生成的.js文件之前):
Module = {};
Module.onRuntimeInitialized = function() {
  postMessage("Worker Ready.");
}

onmessage = function(e){
  console.log("Worker: message from mainThread:" + e.data);
  console.log("Worker: mission start.");
  var p = Module._Pi(e.data);
  postMessage(p);
  console.log("Worker: mission finished.");
}
pre.js中定义了onmessage()回调函数,用于处理来自主线程的消息。onmessage()函数将根据主线程传来的参数计算圆周率,并将计算结果通过postMessage()方法发送回主线程。另外,即使 在Worker中,Module的编译和初始化仍然是异步的。Worker加载完 pre.js文件并不意味着Module运行时可用,仍然需要采取某种通知机制,确保Worker在开始调用Module前Module已经初始化完成。

 这里通过Module.onRuntimeInitialized()回调方法来通知主线程已经准备完毕。

编译pi.cc文件:

 emcc code/1209/pi.cc --pre-js code/1209/pre.js -o code/1209/pi.js

其中--pre-js代表编译成为pi.js的前置文件,与之相对的还有--post-js,之表示后置文件。 

 创建pi.html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        var worker = new Worker("./pi.js");
        worker.onmessage = function (e) {
            console.log("mainThread: message from Worker:" + e.data);
            if (e.data == "Worker Ready.") {
                worker.postMessage(2000);
            }
        }
        setInterval(function () { console.log("mainThread: timer()"); }, 1000);
    </script>
    <script src="pi.js"></script>
</body>

</html>

 当收到Worker Ready.消息确认Worker中的Module准备完毕后,发送任务参数2000给Worker计算圆周率。

在浏览器运行pi.html后F12显示:

同时任务管理器显示浏览器占用:

 

由于Worker中执行的运算,CPU核心处于满负荷状态,但主线程并未阻塞,仍然在定时输出

timer日志。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值