【问题标题】:NodeJS: Native c++ module with multi-threading (openmp)NodeJS:具有多线程的本机 C++ 模块(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"]
      }
    ]
  ]
}  ]}    

【问题讨论】:

    标签: c++ node.js windows multithreading 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 2014-05-02
      • 1970-01-01
      • 1970-01-01
      • 2013-06-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多