WebAssembly多线程demo 一、准备工作 WebAssembly第一个demo chrome://flags WebAssembly threads support 选项要打开 enable
二、好了,开始写demo 功能:js传递给c 一个计算次数,一个启动的线程数, 打印相同计算次数下,单线程和多线程的计算时间
1、新建一个目录,创建两个文件index.html和main.cpp
2、main.cpp内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 #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内容1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <!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、编译
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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会有问题
启动服务在控制台看看效果:
三、编译参数说明 *https://github.com/emscripten-core/emscripten/blob/master/src/settings.js