Rumah > hujung hadapan web > tutorial js > Contoh kaedah untuk menggunakan pengaturcaraan berbilang benang dalam nodejs_node.js

Contoh kaedah untuk menggunakan pengaturcaraan berbilang benang dalam nodejs_node.js

WBOY
Lepaskan: 2016-05-16 16:08:02
asal
2316 orang telah melayarinya

Dalam catatan blog saya sebelum ini Jangan katakan mustahil, laksanakan tidur dalam nodejs , saya memperkenalkan anda kepada penggunaan addon nodejs. Tema hari ini masih addon, teruskan meneroka keupayaan c/c dan tebus kelemahan nodejs.

Saya telah menyebut isu prestasi nodejs berkali-kali. Malah, setakat bahasa itu sendiri, prestasi nodej masih sangat tinggi Walaupun ia tidak sebaik kebanyakan bahasa statik, jurangnya tidak besar berbanding dengan bahasa dinamik yang lain, kelebihan kelajuannya sangat jelas . Tetapi mengapa kita sering mengatakan bahawa nodejs tidak mampu untuk senario intensif CPU? Kerana sifatnya yang berbenang tunggal, ia tidak dapat menggunakan sepenuhnya CPU untuk senario intensif CPU. Terdapat undang-undang Amdahl yang terkenal dalam sains komputer:

Andaikan jumlah beban kerja W boleh diuraikan kepada dua bahagian: Ws yang hanya boleh dikira secara bersiri dan Wp yang membenarkan pengiraan selari. Kemudian, dalam kes pengkomputeran selari p CPU, prestasi boleh dipertingkatkan mengikut masa mempercepatkan. Undang-undang Amdahl menerangkan perkara yang selari boleh dan tidak boleh lakukan. Ini adalah keadaan yang ideal, keadaan sebenar akan menjadi lebih kompleks. Sebagai contoh, konkurensi berkemungkinan menyebabkan perbalahan untuk sumber, memerlukan penambahan pelbagai kunci, yang sering menyebabkan keselarian dalam keadaan menunggu juga akan menyebabkan overhed masa tambahan untuk sistem pengendalian menukar penjadualan benang, meningkatkan Ws; Walau bagaimanapun, apabila Wp jauh lebih besar daripada Ws dalam tugasan dan berbilang teras CPU tersedia, peningkatan prestasi yang dibawa oleh selari adalah ketara.

Baiklah, kembali kepada nodejs. Mari kita bayangkan senario pengiraan: hitung bilangan nombor perdana dalam 4,000,000. Apabila senario ini diprogramkan, operasi pembahagian digunakan terutamanya, dan operasi seperti memori dan objek tidak terlibat Secara teori, ia boleh memastikan bahawa nodejs berjalan pada kelajuan yang agak pantas dan tidak akan ketinggalan terlalu jauh di belakang c, yang sesuai untuk. perbandingan.

Kaedah mencari nombor perdana dalam JavaScript telah disediakan dalam blog ini, salin terus:

Salin kod Kod adalah seperti berikut:

fungsi zhishu_js(bilangan) {
Jika (bilangan == 1) {
         kembali palsu;
}
Jika (bilangan == 2) {
        kembali benar;
}
untuk (var i = 2; i <= Math.sqrt(num); i ) {
Jika (bilangan % i == 0) {
              pulangan palsu;
}
}
Kembalikan benar;
}

Tulis versi bahasa c yang lain:

Salin kod Kod adalah seperti berikut:

#include

bool zhishu(int num){
Jika (bilangan == 1) {
         kembali palsu;
}
Jika (bilangan == 2) {
        kembali benar;
}
untuk (int i = 2; i <= sqrt(num); i ) {
Jika (bilangan % i == 0) {
              pulangan palsu;
}
}
Kembalikan benar;
};

Dalam nodej, kami menggunakan gelung dari 1 hingga 4000000 untuk mendapatkan semula nombor perdana dalam bahasa c, kami menyediakan beberapa utas dan mentakrifkan kiraan sebagai 4000000. Setiap urutan melakukan perkara berikut: jika kiraan lebih daripada 0, keluarkannya; Nilai kiraan, dan mengira sama ada ia adalah nombor perdana, dan pengurangan dikira sebanyak 1. Mengikut idea ini, versi javascript mudah ditulis:

Salin kod Kod adalah seperti berikut:

kiraan var = 0;

untuk (j = 1; j < 4000000; j ) {
Jika(zhishu(j)){
Kira ;
}
}


Kesukaran utama ialah pengaturcaraan berbilang benang dalam bahasa C. Pada hari-hari awal c/c, keperluan untuk pengkomputeran selari tidak dipertimbangkan, jadi sokongan multi-threading tidak disediakan dalam perpustakaan standard. Sistem pengendalian yang berbeza biasanya mempunyai pelaksanaan yang berbeza. Untuk mengelakkan masalah ini, kami menggunakan pthread untuk mengendalikan benang.

Muat turun versi terkini pthread. Memandangkan saya tidak biasa dengan gyp, saya mengambil masa yang lama untuk membetulkan lib kebergantungan pautan Akhirnya, kaedah saya ialah meletakkan terus kod sumber pthread dalam direktori projek, dan menambah pthread.c pada kod sumber. senarai dalam binding.gyp , susun pthread sekali semasa menyusun projek. Binding.gyp yang diubah suai kelihatan seperti ini:

Salin kod Kod adalah seperti berikut:

{
"sasaran": [
{
"target_name": "hello",
"sumber": [ "hello.cc","pthreads/pthread.c" ],
"include_dirs": [
" “pthread”
],
"perpustakaan": ["Ws2_32.lib"]
}
]
}

Sudah tentu, kaedah saya sangat menyusahkan Jika anda hanya menambah rujukan kepada lib dan memasukkan direktori dalam pthread, dan tidak ada masalah pergantungan, itu adalah yang terbaik.

Kemudian mari kita masuk ke segala-galanya tentang C/C multi-threading dan tentukan fungsi pemprosesan thread:

Salin kod Kod adalah seperti berikut:

kunci pthread_mutex_t;

void *thread_p(void *null){
int num, x=0;
lakukan{
          pthread_mutex_lock(&lock);
         num=count--;
         pthread_mutex_unlock(&lock);
Jika(bilangan>0){
Jika(zhishu(bilangan))x ;
         }lain{
             rehat;
}
}semasa(benar);
std::cout<<' '< pthread_exit(NULL);
        pulangkan null;
}

Antara utas, pembolehubah kiraan bersaing antara satu sama lain Kita perlu memastikan bahawa hanya satu utas boleh mengendalikan pembolehubah kiraan pada masa yang sama. Kami menambah kunci mutex melalui kunci pthread_mutex_t;. Apabila pthread_mutex_lock(&lock); Sejajar dengan itu, pthread_mutex_unlock(&lock);

Memandangkan pengkompil melakukan pengoptimuman kompilasi semasa menyusun, jika penyata tidak melakukan apa-apa dengan jelas dan tidak memberi kesan kepada pelaksanaan penyataan lain, ia akan dioptimumkan oleh pengkompil. Dalam kod di atas, saya menambah kod untuk mengira bilangan nombor perdana Jika tidak, ia akan kelihatan seperti ini:

Salin kod Kod adalah seperti berikut:

untuk (int j = 0; j < 4000000; j ) {
zhishu(j);
}

akan dilangkau terus oleh pengkompil dan tidak akan berjalan sebenarnya.

Kaedah penulisan menambah addon telah diperkenalkan Kami menerima parameter daripada javascript, menunjukkan bilangan utas, dan kemudian mencipta bilangan utas yang ditentukan dalam c untuk melengkapkan pengambilan nombor perdana. Kod lengkap:

Salin kod Kod adalah seperti berikut:

#include
#include
#include
#include "pthreadspthread.h"
#define MAX_THREAD 100
menggunakan ruang nama v8;

bilangan int=4000000;
pthread_t tid[MAX_THREAD];
kunci pthread_mutex_t;

void *thread_p(void *null){
    int num, x=0;
    lakukan{
        pthread_mutex_lock(&lock);
        num=count--;
        pthread_mutex_unlock(&lock);
        jika(bilangan>0){
            if(zhishu(num))x ;
        }lain{
            rehat;
        }
    }semasa(benar);
    std::cout<<' '<     pthread_exit(NULL);
    kembalikan null;
}

KAEDAH_NAN(Zhishu){
    NanScope();
    pthread_mutex_init(&kunci,NULL);
    double arg0=args[0]->NumberValue();
    int c=0;
    untuk (int j = 0; j < arg0 && j         pthread_create(&tid[j],NULL,thread_p,NULL);
    }
    untuk (int j = 0; j < arg0 && j         pthread_join(tid[j],NULL);
    }
    NanReturnUndefined();
}

batal Init(Kendalikan eksport){
    eksport->Set(NanSymbol("zhishu"), FunctionTemplate::New(Zhishu)->GetFunction());
}

MODUL_NODE(hello, Init);

phread_create线程 sertai,直到子线程退出。如果子线程已退出,则phread_join不会做任何事。所以对所有的线程都执行thread_join,可以保证所有的线程退出后才会例主秿程眼绿程经

完善一下nodejs脚本:


复制代码 代码如下:
var zhishu_c=require('./build/Release/hello.node').zhishu;
fungsi zhishu(bilangan) {
    jika (bilangan == 1) {
        pulangkan palsu;
    }
    jika (bilangan == 2) {
        kembali benar;
    }
    untuk (var i = 2; i <= Math.sqrt(num); i ) {
        jika (bilangan % i == 0) {
            pulangkan palsu;
        }
    }
    kembali benar;
}

console.time("c");     zhishu_c(100);

console.timeEnd("c");

console.time("js");

var count=0;

untuk (j = 1; j < 4000000; j ) {
    jika(zhishu(j)){
        kira ;
    }
}
console.log(count);
console.timeEnd("js");

Lihat keputusan ujian:

Dalam urutan tunggal, walaupun kelajuan larian C/C ialah 181% daripada nodej, kami berpendapat hasil ini masih sangat baik dalam bahasa dinamik. Peningkatan kelajuan adalah paling jelas apabila menggunakan dwi benang Itu kerana komputer saya mempunyai dwi-teras empat-benang CPU, dan ada kemungkinan dua teras sedang digunakan untuk pemprosesan pada masa ini. Kelajuan mencapai maksimum apabila terdapat 4 utas Pada masa ini, ia sepatutnya menjadi had yang boleh dicapai dwi-teras dan empat utas Apabila bilangan utas bertambah, kelajuan tidak boleh dipertingkatkan. Dalam undang-undang Amdahl di atas, p telah mencapai had atas 4. Menambah lebih banyak utas akan meningkatkan masa penjadualan proses sistem pengendalian dan masa kunci Walaupun ia juga akan meningkatkan persaingan untuk masa CPU, secara keseluruhan, peningkatan dalam W akan lebih jelas dan prestasi akan berkurangan. Jika anda melakukan percubaan ini pada mesin terbiar, data harus lebih baik.

Daripada eksperimen ini, kita boleh membuat kesimpulan bahawa untuk operasi intensif CPU, kecekapan akan banyak dipertingkatkan jika dibiarkan kepada bahasa statik Jika pengiraan melibatkan lebih banyak memori, rentetan, tatasusunan, rekursi, dsb (untuk disahkan kemudian), peningkatan prestasi adalah lebih menakjubkan. Pada masa yang sama, penggunaan rasional berbilang benang boleh meningkatkan kecekapan pemprosesan dengan berkesan, tetapi lebih banyak benang tidak semestinya lebih baik ia mesti dikonfigurasikan dengan sewajarnya mengikut keadaan mesin.

Nodejs sendiri memang tidak pandai mengendalikan tugasan intensif CPU, tetapi dengan pengalaman artikel ini, saya rasa tidak mustahil untuk mengatasi halangan ini.

Label berkaitan:
sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan