NodeJS:具有多线程的本机 C++ 模块(openmp)

Posted

技术标签:

【中文标题】NodeJS:具有多线程的本机 C++ 模块(openmp)【英文标题】:NodeJS: Native c++ module with multi-threading (openmp) 【发布时间】:2016-07-15 00:30:04 【问题描述】:

我有一个非常基本的 NodeJS 原生模块,它基本上包装了一个更复杂的 c++ 程序,其中包括使用 OpenMP 的多线程(它是蒙特卡罗模拟)。这个 c++ 程序可以单独运行,并且在使用 cython 模块从 python 调用来包装 c++ 代码时运行良好。但是,当我将它编译为本机节点模块(使用 /OpenMP 作为 MSBuild 编译器的参数)时,它只使用一个线程。

以下是我的binding.gyp供参考:

  "targets": [

  "target_name": "LossForecast",
  "sources": [ "NodeLossForecast.cpp", "src/AutoDiff.cpp" ],
  "include_dirs":["src", "<!(node -e \"require('nan')\")"],
  'conditions': [
    ['OS=="win"', 
      
        'cflags': ["/EHsc", "/O2", "/openmp"]
      
    ]
  ]
  ]    

【问题讨论】:

【参考方案1】:

所以,我正在写下我的文件,以便使用 OpenMP 运行一个简单的node-addon-api pi 程序。虽然node-addon-api 是实验性的,但它很快就会作为node.js 的官方api 发布。它非常简单。

这仅适用于 Windows。我可以确认它是否在多个处理器中运行。

binding.gyp


    "targets": [
        
            "target_name": "nodeOpenMP",
            "defines": [
                "VERSION=0.0.1",
                "NAPI_DISABLE_CPP_EXCEPTIONS"
            ],
            "sources": [
                "module.cc"
            ],
            "include_dirs": [
                "<!(echo %cd%/node_modules/node-addon-api)"               
            ],
            "conditions": [
                [
                    'OS=="win"',
                    
                        'msvs_settings': 
                            'VCCLCompilerTool' : 
                                'AdditionalOptions' : ['/MT','/openmp']
                            
                         
                    
                ]
            ]
        
    ]

您必须添加VCCLCompilerTool,然后在AdditionalOptions 下添加`/openmp',如上所述。

这是我编写的一个简单的 PI 程序,

module.cc

#include <napi.h>
#include <omp.h>
#include <iostream>
#include <windows.h>    // for GetCurrentProcessorNumber()

int getThreads()
    // Get number of threads
    omp_set_num_threads(3);
    int n = 0;
    #pragma omp parallel reduction(+:n)
        n += 1;
    return n;


double GetPi(short numOfThreads,long numberOfSteps)
    long i;
    double pi, sum = 0.0;
    double step = 1.0/(double) numberOfSteps;

    omp_set_num_threads(numOfThreads);

    #pragma omp parallel
    
        std::cout << "This thread is running on processor: " << GetCurrentProcessorNumber() << "\n";
        double x;
        #pragma omp for reduction(+:sum) 
            for(i = 0; i < numberOfSteps; i++) 
                x = ( i + 0.5 ) * step;
                sum += 4.0 / (1 + x*x);
             
    

    std::cout << "Total no. of threads (not processors)" <<getThreads() << std::endl;
    pi =  step * (double)sum;
    return pi;


Napi::Value calculatePi(const Napi::CallbackInfo& info )
     Napi::Env env = info.Env();

    // check for no. of arguments
    if(info.Length()<2)
        Napi::TypeError::New(env, "Wrong number of arguments").ThrowAsjavascriptException();
        return env.Null();
    

    if (!info[0].IsNumber() || !info[1].IsNumber()) 
        Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
        return env.Null();
    

    double numThreads = info[0].As<Napi::Number>().DoubleValue();
    double numSteps = info[1].As<Napi::Number>().DoubleValue();

    double pi = GetPi(numThreads, numSteps);

    Napi::Number PI = Napi::Number::New(env, pi);

    return PI;


Napi::Object Init(Napi::Env env, Napi::Object exports)
    // register the functions that are to be exported    
    exports.Set(Napi::String::New(env, "pi"), Napi::Function::New(env, calculatePi));
    return exports;


NODE_API_MODULE(nodeOpenMP, Init);

testOMP.js

const omp = require("./build/Release/nodeOpenMP");
const numThreads = 4, numSteps = 1000000;
console.log( numThreads, numSteps );

相应地复制粘贴上面的文件。不要忘记安装node-addon-api(locally) 和node-gyp(globally) 然后运行:

node-gyp configure build &amp;&amp; node --no-warnings testOMP.js

你应该得到这样的输出:

This thread is running on processor: 3
This thread is running on processor: 3
This thread is running on processor: 0
This thread is running on processor: 3
Total no. of threads (not processors): 3

我正在考虑尽快制作一个跨平台的 npm 包node-openmp

关注这个 repo 并做出贡献。我愿意接受任何贡献。 Himujjal/node-openmp

【讨论】:

以上是关于NodeJS:具有多线程的本机 C++ 模块(openmp)的主要内容,如果未能解决你的问题,请参考以下文章

nodejs是单线程还是多线程

调用本机代码的多线程托管应用程序

具有全局变量的 C++ 多线程

Nodejs学习之多进程架构

如果 ANSI C++ 不支持多线程,非托管 C++ 应用程序如何实现多线程?

NodeJS 多线程编程