WebAssembly多线程demo
一、准备工作
WebAssembly第一个demo
chrome://flags WebAssembly threads support 选项要打开 enable
二、好了,开始写demo
功能:js传递给c 一个计算次数,一个启动的线程数, 打印相同计算次数下,单线程和多线程的计算时间
1、新建一个目录,创建两个文件index.html和main.cpp
2、main.cpp内容
#include <iostream>
#include <future>
#include <math.h>
#include <vector>
#include <chrono>
#include <sstream>
#include <emscripten.h>
#include <unistd.h>
using namespace std;
using namespace chrono;
//相加
int add(int start,int end){
int result = 0;
for(int i = start;i<end;i++){
result += i;
usleep (1000);
}
return result;
}
//线程
int openThreadAndAdd(int size,int threadNum){
//创建线程结果存放数组
vector<future<int>> futures;
futures.reserve(threadNum);
//每个线程计算多少个<相加>
double step = ((double)size / (double)threadNum);
step = ceil(step);
long startIndex = 0;
long endIndex = step;
for(long i=0;i < threadNum; i++){
//启动线程
auto future = async(launch::async,add,startIndex,endIndex);
//把线程结果存在数组里
futures.push_back(move(future));
//步进
startIndex += step;
endIndex += step;
//判断是否结束
if(endIndex > size ){
endIndex = size;
}
}
//把多线程的计算结果<相加>
int total = 0;
for(auto& future : futures){
total = add(total,future.get());
}
//回收数组
futures.clear();
return total;
}
//获取当前时间
system_clock::time_point getTime(){
return system_clock::now();
}
//获取时间差
double cost(system_clock::time_point start){
system_clock::time_point end = getTime();
auto duration = duration_cast<microseconds>(end - start);
double cost = double(duration.count()) * microseconds::period::num / microseconds::period::den;
return cost;
}
//计算单线程和多线程,并打印结果
const char* computer(int size,int threadNum){
//多线程
auto start1 = getTime();
int total_thread = openThreadAndAdd(size,threadNum);
double costTime1 = cost(start1);
//单线程
auto start2 = getTime();
int total = add(0,size);
double costTime2 = cost(start2);
//生成结果字符串
string str = "thread:" + to_string(total_thread) + " cost:" + to_string(costTime1) + "\n";
str = str + "normal:" + to_string(total) + " cost:" +to_string(costTime2);
const char* result = str.c_str();
return result;
}
extern "C" {
EMSCRIPTEN_KEEPALIVE
const char* jsCallC(int size,int threadNum) {
cout << "jsCallC" << endl;
const char* result = computer(size + 1,threadNum);
return result;
}
}
- 给js调用的方法必须标注EMSCRIPTEN_KEEPALIVE
3、index.html内容
<!DOCTYPE html>
<html>
<head>
<script src="./webassembly.js"></script>
</html>
<script type="text/javascript">
function fun(){
var size = 1000
var threadNum = 4;
var outputPtr = Module._jsCallC(size,threadNum)
var outputStr = Module.UTF8ToString(outputPtr) //排序结果指针转字符串
console.log(outputStr);
Module._free(outputPtr);
}
初始化webasembly
Module.onRuntimeInitialized = function() {
console.log("ModuleWASM_INSTANCE init finish")
fun()
}
</script>
4、编译
emsdkDir='emsdk的路径'
emsdk activate latest
source ${emsdkDir}/emsdk_env.sh
emcc main.cpp \
-std=c++11 \
-s WASM=1 \
-s EXTRA_EXPORTED_RUNTIME_METHODS=["UTF8ToString"] \
-s EXPORTED_FUNCTIONS=["_jsCallC"] \
-pthread \
-s PROXY_TO_PTHREAD=1 \
-s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=7 \
-s TOTAL_MEMORY=512MB --memory-init-file 1 \
-O1 -o webassembly.js
- -pthread -s USE_PTHREADS=1 -s PROXY_TO_PTHREAD=1 开启多线程
- -s PTHREAD_POOL_SIZE=7 开启7个线程
- -s TOTAL_MEMORY=512MB 多线程需要制定内存容量
- –memory-init-file 1 指定开辟单独的内存,和上面一个参数同时使用
- 注意:开启多线程时,开启-s MODULARIZE=1会有问题
启动服务在控制台看看效果:
- python2:python -m SimpleHTTPServer 8080
python3:python -m http.server 8080
三、编译参数说明
*https://github.com/emscripten-core/emscripten/blob/master/src/settings.js