2017-05-18 11 views
20

में बड़ी सरणी पास करें मेरे पास जटिल सीपीयू गहन कार्य है जो मैं एक बड़े सरणी पर करना चाहता हूं। आदर्श रूप में, मैं इसे बाल प्रक्रिया में पास करना चाहता हूं।नोड बाल प्रक्रिया

var spawn = require('child_process').spawn; 

// dataAsNumbers is a large 2D array 
var child = spawn(process.execPath, ['/child_process_scripts/getStatistics', dataAsNumbers]); 

child.stdout.on('data', function(data){ 
    console.log('from child: ', data.toString()); 
}); 

लेकिन जब मैं करते हैं, नोड त्रुटि देता है:

spawn E2BIG

मैं तो बच्चे की प्रक्रिया के लिए डेटा पाइप भर में this article

आया जाने का रास्ता हो रहा है। मेरे कोड है:

var spawn = require('child_process').spawn; 

console.log('creating child........................'); 

var options = { stdio: [null, null, null, 'pipe'] }; 
var args = [ '/getStatistics' ]; 
var child = spawn(process.execPath, args, options); 

var pipe = child.stdio[3]; 

pipe.write(Buffer('awesome')); 

child.stdout.on('data', function(data){ 
    console.log('from child: ', data.toString()); 
}); 

और फिर getStatistics.js में:

console.log('im inside child'); 

process.stdin.on('data', function(data) { 
    console.log('data is ', data); 
    process.exit(0); 
}); 

हालांकि process.stdin.on में कॉलबैक पूरा नहीं हुआ है। मैं अपने बच्चे की स्क्रिप्ट में स्ट्रीम कैसे प्राप्त कर सकता हूं?

संपादित

मैं बफर दृष्टिकोण का परित्याग करने के लिए किया था। अब मैं एक संदेश के रूप सरणी भेज रहा:

var cp = require('child_process'); 
var child = cp.fork('/getStatistics.js'); 

child.send({ 
    dataAsNumbers: dataAsNumbers 
}); 

लेकिन यह केवल काम करता है जब dataAsNumbers की लंबाई लगभग 20,000 से नीचे है, अन्यथा यह समय समाप्त।

+0

नोड इस प्रकार के काम के लिए सही उपकरण नहीं है। मैं आपको एक बहुप्रचारित भाषा का उपयोग करने की सलाह दूंगा। – arboreal84

+0

परियोजना 90% पूर्ण है, मैं अब नोड से बदल नहीं रहा हूं। नोड – Mark

+1

के साथ भारी CPU उपयोग को समझाते हुए बहुत से लेख हैं, आमतौर पर कोर समस्याओं को हल करने के लिए एक परियोजना शुरू करना एक अच्छा विचार है। एक बहुप्रचारित भाषा में आपको थ्रेड साझा स्मृति के बाद डेटा कॉपी करने की आवश्यकता नहीं होगी। इस मामले में डेटा की प्रतिलिपि सबकुछ धीमा कर देगी। इसके अलावा, जब आप libuv को काम सौंपते हैं तो नोड तेज़ होता है। यदि आप भारी प्रसंस्करण के लिए नोड के v8 भाग का उपयोग करने की योजना बना रहे हैं तो यह तेज़ नहीं होगा। इसके अलावा, अगर किसी भी कारण से यह वास्तविक सर्वर का हिस्सा है, तो आपका इवेंट लूप अवरुद्ध हो जाएगा और I/O आपके सभी अनुरोधों को समय निकाल देगा। – arboreal84

उत्तर

10

इतनी बड़ी मात्रा में डेटा के साथ, मैं डेटा प्रक्रिया में डेटा की प्रतिलिपि बनाने के बजाय shared memory का उपयोग करने के लिए देखता हूं (जो तब होता है जब आप पाइप या पास संदेश का उपयोग करते हैं)। यह स्मृति को बचाएगा, पैरेंट प्रक्रिया के लिए कम CPU समय लेगा, और कुछ सीमा में टक्कर मारने की संभावना नहीं है।

shm-typed-array एक बहुत ही सरल मॉड्यूल है जो आपके एप्लिकेशन के अनुकूल लगता है। उदाहरण:

parent.js

"use strict"; 

const shm = require('shm-typed-array'); 
const fork = require('child_process').fork; 

// Create shared memory 
const SIZE = 20000000; 
const data = shm.create(SIZE, 'Float64Array'); 

// Fill with dummy data 
Array.prototype.fill.call(data, 1); 

// Spawn child, set up communication, and give shared memory 
const child = fork("child.js"); 
child.on('message', sum => { 
    console.log(`Got answer: ${sum}`); 

    // Demo only; ideally you'd re-use the same child 
    child.kill(); 
}); 
child.send(data.key); 

child.js

"use strict"; 

const shm = require('shm-typed-array'); 

process.on('message', key => { 
    // Get access to shared memory 
    const data = shm.get(key, 'Float64Array'); 

    // Perform processing 
    const sum = Array.prototype.reduce.call(data, (a, b) => a + b, 0); 

    // Return processed data 
    process.send(sum); 
}); 

ध्यान दें कि हम केवल भारतीय दंड संहिता के माध्यम से बच्चे की प्रक्रिया के लिए माता-पिता से एक छोटी सी "कुंजी" भेज रहे हैं , पूरा डेटा नहीं। इस प्रकार, हम स्मृति और समय का एक टन बचाते हैं।

बेशक, आप 'Float64Array' (उदा। double) बदल सकते हैं जो आपके आवेदन की आवश्यकता है typed array। ध्यान दें कि यह लाइब्रेरी विशेष रूप से केवल एकल-आयामी टाइप किए गए सरणी को संभालती है; लेकिन यह केवल एक मामूली बाधा होना चाहिए।

-1

लंबी प्रक्रिया कार्यों के लिए आप gearman जैसे कुछ का उपयोग कर सकते हैं आप श्रमिकों पर भारी कार्य प्रक्रिया कर सकते हैं, इस तरह आप सेटअप कर सकते हैं कि आपको कितने श्रमिकों की आवश्यकता है, उदाहरण के लिए यदि मुझे आवश्यकता है तो मैं कुछ फाइल प्रोसेसिंग करता हूं स्केल आप अधिक कार्यकर्ता उदाहरण बनाते हैं, मेरे पास अलग-अलग कार्यों के लिए अलग-अलग कर्मचारी हैं, ज़िप फ़ाइलों को संसाधित करते हैं, थंबनेल जेनरेट करते हैं, इसका अच्छा यह है कि श्रमिकों को किसी भी भाषा node.js, Java, पायथन पर लिखा जा सकता है और इसे एकीकृत किया जा सकता है आसानी से अपनी परियोजना

// worker-unzip.js 
const debug = require('debug')('worker:unzip'); 
const {series, apply} = require('async'); 
const gearman = require('gearmanode'); 
const {mkdirpSync} = require('fs-extra'); 
const extract = require('extract-zip'); 

module.exports.unzip = unzip; 
module.exports.worker = worker; 

function unzip(inputPath, outputDirPath, done) { 
    debug('unzipping', inputPath, 'to', outputDirPath); 
    mkdirpSync(outputDirPath); 
    extract(inputPath, {dir: outputDirPath}, done); 
} 


/** 
* 
* @param {Job} job 
*/ 
function workerUnzip(job) { 
    const {inputPath, outputDirPath} = JSON.parse(job.payload); 
    series([ 
    apply(unzip, inputPath, outputDirPath), 
    (done) => job.workComplete(outputDirPath) 
    ], (err) => { 
    if (err) { 
     console.error(err); 
     job.reportError(); 
    } 
    }); 
} 

function worker(config) { 
    const worker = gearman.worker(config); 
    if (config.id) { 
    worker.setWorkerId(config.id); 
    } 

    worker.addFunction('unzip', workerUnzip, {timeout: 10, toStringEncoding: 'ascii'}); 
    worker.on('error', (err) => console.error(err)); 

    return worker; 
} 

एक सरल index.js

const unzip = require('./worker-unzip').worker; 

unzip(config); // pass host and port of the Gearman server 

मैं आम तौर पर पीएम 2

के साथ श्रमिकों को चलाता हूं जो आपके कोड के साथ एकीकरण है। जैसे

//initialize 
const gearman = require('gearmanode'); 

gearman.Client.logger.transports.console.level = 'error'; 
const client = gearman.client(configGearman); // same host and port 

कुछ बस कार्यों

const taskpayload = {inputPath: '/tmp/sample-file.zip', outputDirPath: '/tmp/unzip/sample-file/'} 
const job client.submitJob('unzip', JSON.stringify(taskpayload)); 
job.on('complete', jobCompleteCallback); 
job.on('error', jobErrorCallback); 
0

मैं भी देरी अपने अनुभव कर रहे थे पुन: पेश करने में सक्षम था के नाम से गुजर रहा कतार में कार्यालय जोड़ सकते हैं लेकिन हो सकता है आप के रूप में के रूप में बुरा नहीं। मैं प्रयोग किया जाता है निम्नलिखित

// main.js 
const fork = require('child_process').fork 

const child = fork('./getStats.js') 

const dataAsNumbers = Array(100000).fill(0).map(() => 
    Array(100).fill(0).map(() => Math.round(Math.random() * 100))) 

child.send({ 
    dataAsNumbers: dataAsNumbers, 
}) 

और

// getStats.js 
process.on('message', function (data) { 
    console.log('data is ', data) 
    process.exit(0) 
}) 

node main.js 2.72s user 0.45s system 103% cpu 3.045 total

मैं 100k अपने डेटा उपहास करने के लिए, सुनिश्चित करें कि आप process पर message घटना उपयोग कर रहे हैं 100 संख्या से बना तत्वों पैदा कर रहा हूँ। लेकिन हो सकता है कि आपके बच्चे अधिक जटिल हों और विफलता का कारण हो, यह भी आपकी क्वेरी पर सेट किए गए टाइमआउट पर निर्भर करता है।


आप बेहतर परिणाम प्राप्त करना चाहते हैं, क्या तुम कर सकते हो कई टुकड़ों है कि बच्चे की प्रक्रिया के लिए भेजा जाएगा और प्रारंभिक सरणी के रूप में पुनर्निर्मित में अपने डेटा हिस्सा है।


भी एक संभावना है, एक तीसरी पार्टी पुस्तकालय या प्रोटोकॉल का उपयोग करने भले ही यह थोड़ा अधिक काम है किया जाएगा। आप messenger.js या यहां तक ​​कि एएमक्यूपी कतार की तरह कुछ भी देख सकते हैं जो आपको पूल के साथ दो प्रक्रियाओं के बीच संवाद करने की अनुमति दे सकता है और उप प्रक्रिया द्वारा संदेश की गारंटी की गारंटी देता है। इसके कुछ नोड कार्यान्वयन हैं, जैसे amqp.node, लेकिन इसके लिए अभी भी कुछ सेटअप और कॉन्फ़िगरेशन कार्य की आवश्यकता होगी।

0

https://github.com/ptarjan/node-cache जैसे मेमोरी कैश में उपयोग करें, और माता-पिता को सरणी सामग्री को कुछ कुंजी के साथ स्टोर करने दें, बच्चे की प्रक्रिया उस कुंजी के माध्यम से सामग्री को पीछे हटाना चाहती है।

0

आप अपने नोड बच्चे के आवेदन में इनपुट के रूप में ओएस पाइप you'll find a gist here का उपयोग करने पर विचार कर सकते हैं।

मुझे पता है कि यह वही नहीं है जो आप पूछ रहे हैं, लेकिन आप cluster मॉड्यूल (नोड में शामिल) का उपयोग कर सकते हैं। इस तरह आप कई उदाहरण प्राप्त कर सकते हैं क्योंकि कोर को आपको मशीन को प्रोसेसिंग तेज करना है। इसके अलावा यदि आप प्रसंस्करण शुरू करने से पहले सभी डेटा उपलब्ध कराने की आवश्यकता नहीं है तो स्ट्रीम का उपयोग करने पर विचार करें। यदि संसाधित होने वाला डेटा बहुत बड़ा है तो मैं इसे एक फ़ाइल में संग्रहीत करता हूं ताकि प्रक्रिया के दौरान कोई त्रुटि हो तो आप फिर से बदल सकें। यहां क्लस्टरिंग का एक उदाहरण है।

var cluster = require('cluster'); 
var numCPUs = 4; 

if (cluster.isMaster) { 
    for (var i = 0; i < numCPUs; i++) { 
     var worker = cluster.fork(); 
     console.log('id', worker.id) 
    } 
} else { 
    doSomeWork() 
} 

function doSomeWork(){ 
    for (var i=1; i<10; i++){ 
     console.log(i) 
    } 
} 

अधिक जानकारी कर्मचारियों को question 8534462 पर संदेश भेजना।

0

आप एक उपप्रजाति क्यों बनाना चाहते हैं? सबप्रोसेसेस में डेटा भेजने से सीपीयू और रीयलटाइम के मामले में अधिक लागत लग सकती है, इससे पहले कि आप प्रक्रिया को उसी प्रक्रिया में पूरा कर सकें।

इसके बजाय, मैं सुझाव दूंगा कि सुपर कुशल कोडिंग के लिए आप एक कार्यकर्ता थ्रेड में अपनी आंकड़े गणना करने पर विचार करते हैं जो नोडजेस की मुख्य प्रक्रिया के समान स्मृति में चलता है।

आप NAN का उपयोग सी ++ कोड लिखने के लिए कर सकते हैं जिसे आप एक कार्यकर्ता थ्रेड पर पोस्ट कर सकते हैं, और उसके बाद उस कार्यकर्ता धागे को परिणाम पोस्ट करने के लिए और एक ईवेंट वापस अपने नोडजेज़ ईवेंट लूप पर किया जा सकता है।

इसका लाभ यह है कि आपको डेटा को एक अलग प्रक्रिया में भेजने के लिए अतिरिक्त समय की आवश्यकता नहीं है, लेकिन नकारात्मक बात यह है कि आप थ्रेडेड एक्शन के लिए थोड़ा सी ++ कोड लिखेंगे, लेकिन एनएएन एक्सटेंशन को चाहिए आपके लिए सबसे कठिन कार्य का ख्याल रखना।

+0

मुझे लगता है कि वह एकाधिक कोर – GroovyDotCom

+1

का उपयोग करना चाहता है यदि आप इसे एक वर्कर थ्रेड पर दबाते हैं तो आप एकाधिक कोर का उपयोग करेंगे – Soren

संबंधित मुद्दे