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

时间:2016-07-15 00:30:05

标签: c++ node.js windows multithreading openmp

我有一个非常基本的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 个答案:

答案 0 :(得分:3)

所以,我正在写下我的文件,用于使用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(本地)和node-gyp(全局),然后运行:

node-gyp configure build && 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

关注此回购并做出贡献。我愿意接受任何贡献。 Himujjal/node-openmp