জাভাস্ক্রিপ্ট মাল্টিথ্রেডিং সমর্থন সহ সমান্তরাল কৌশল সম্পাদন

লেখক:এফএমজেড-লিডিয়া, তৈরিঃ 2023-03-07 15:12:04, আপডেটঃ 2023-09-18 20:04:21

Concurrent Strategy Execution with JavaScript Multithreading Support

কৌশল প্রোগ্রাম সমান্তরালভাবে চালানো যাক, এবং জাভাস্ক্রিপ্ট কৌশল সিস্টেমের নীচে মাল্টি থ্রেড সমর্থন যোগ

জাভাস্ক্রিপ্ট ভাষা ব্যবহার করে এফএমজেডে কৌশলগুলি বিকাশ করার সময়, যেহেতু কৌশল স্থাপত্যটি জরিপ করা হয়।exchange.Goফাংশনটি কিছু ইন্টারফেসে সমান্তরাল কল করতে ব্যবহৃত হয়, যাতে কিছু সমান্তরাল দৃশ্যের প্রয়োজনীয়তা পূরণ করা যায়। তবে আপনি যদি একাধিক ক্রিয়াকলাপ সম্পাদন করতে একটি একক থ্রেড তৈরি করতে চান তবে এটি অসম্ভব। উদাহরণস্বরূপ পাইথন ভাষার মতো,threadingলাইব্রেরী কিছু সমান্তরাল নকশা করতে.

এই প্রয়োজনীয়তার ভিত্তিতে, এফএমজেড প্ল্যাটফর্মটি সিস্টেমের নীচের স্তরটি আপগ্রেড করেছে। জাভাস্ক্রিপ্ট ভাষায় সত্যিকারের মাল্টিথ্রেডিং সমর্থনও যুক্ত করা হয়েছে। বিস্তারিত বৈশিষ্ট্যগুলির মধ্যে রয়েছেঃ

  • একই সময়ে কাস্টম ফাংশন চালানোর জন্য থ্রেড তৈরি করুন।
  • ইন্টার-থ্রেড যোগাযোগ।
  • ভাগ করা থ্রেডের মধ্যে সংরক্ষিত ভেরিয়েবল।
  • সম্পদ পুনরুদ্ধার করতে এবং এক্সিকিউশন ফলাফল ফেরত দেওয়ার জন্য থ্রেডটি শেষ হওয়ার জন্য অপেক্ষা করুন।
  • জোরপূর্বক থ্রেড শেষ করুন এবং সম্পদ পুনরুদ্ধার করুন।
  • সমান্তরাল থ্রেড এক্সিকিউশন ফাংশনে বর্তমান থ্রেড আইডি পান।

পরবর্তী, আমি আপনাকে প্রতিটি ফাংশন একের পর এক বুঝতে সাহায্য করব।

একই সময়ে কাস্টম ফাংশন চালানোর জন্য থ্রেড তৈরি করুন

দ্য__Threadফাংশন একটি থ্রেড তৈরি করতে পারেন এবং একই সময়ে একটি ফাংশন চালানো. উদাহরণস্বরূপ, আপনি একটি সমান্তরাল ফাংশন তৈরি করতে হবেfunc1, কি করেfunc1আমরা এটিকে 0 থেকে 9 পর্যন্ত জমা হতে দিতে পারি। ধীরে ধীরে জমা হওয়ার প্রক্রিয়াটি দেখার জন্য, আমরা ফাংশন 1 এর ফর লুপটি ব্যবহার করি যাতে প্রতিটি সময় বিরতি দেওয়া হয় (স্লিপ ফাংশনটি নির্দিষ্ট সংখ্যক মিলিসেকেন্ডের জন্য ঘুমাতে ব্যবহৃত হয়) নির্দিষ্ট সময়ের জন্য।

function func1(sleepMilliseconds) {
    var sum = 0 
    for (var i = 0 ; i < 10 ; i++) {
        sum += i 
        Sleep(sleepMilliseconds)
        Log("sum:", sum)
    }
    
    return sum
}

function main() {
    // Use the __Thread function to create a thread concurrently, and the parameter 200 is the parameter of the func1 function,
    // If the func1 function has multiple parameters, here we pass the corresponding parameters.
    var thread1Id = __Thread(func1, 200)
    
    // Here we need to wait for the execution result of the thread whose thread Id is thread1Id, otherwise all threads will be released directly after the main function is executed.
    var ret = __threadJoin(thread1Id)
    Log("ret:", ret)
}

ব্যবহারিক প্রয়োগে, আমরা একই সাথে http অনুরোধ করতে পারি এইভাবেঃ

function main() {
    let threads = [
        "https://www.baidu.com",
        "https://www.163.com"
    ].map(function(url) {
        return __Thread(function(url) {
            Log("GET", url)
            return HttpQuery(url)
        }, url)
    })
    threads.forEach(function(tid) {
        Log(__threadJoin(tid))
    })
}

থ্রেড এক্সিকিউশনের শেষ পর্যন্ত অপেক্ষা করুন রিসোর্স পুনরুদ্ধার করতে এবং এক্সিকিউশন ফলাফল ফেরত

উপরের উদাহরণে, আমরা__threadJoinমূল ফাংশনে ফাংশন অবশেষে সমান্তরাল থ্রেড শেষ করার জন্য অপেক্ষা করুন।retরিটার্ন মান পায়__threadJoinফাংশন, এবং আমরা রিটার্ন মান মুদ্রণ, আমরা সমান্তরাল থ্রেড এক্সিকিউশন নির্দিষ্ট ফলাফল পর্যবেক্ষণ করতে পারেন.

// id: thread ID, terminated: whether it was forced to stop, elapsed: time-consuming (nanoseconds), ret: the return value of the thread execution function
ret: {"id":1,"terminated":false,"elapsed":2004884301,"ret":45}

জোর করে থ্রেড শেষ করুন এবং সম্পদ পুনরুদ্ধার করুন

function func1(sleepMilliseconds) {
    var sum = 0 
    for (var i = 0 ; i < 10 ; i++) {
        sum += i 
        Sleep(sleepMilliseconds)
        Log("sum:", sum)
    }
    
    return sum
}

function main() {
    var thread1Id = __Thread(func1, 200)
    Sleep(1000)
    retThreadTerminate = __threadTerminate(thread1Id)
    Log(retThreadTerminate)   // true
}

আমরা এখনও এই উদাহরণটি ব্যবহার করছি, একটি থ্রেড তৈরি করার পরে, আপনি 1 সেকেন্ড অপেক্ষা করার পর জোর করে থ্রেডের কার্যকরকরণ বন্ধ করতে পারেন।

থ্রেডের মধ্যে যোগাযোগ

ইন্টার-থ্রেড যোগাযোগ প্রধানত ব্যবহার করে__threadPostMessageফাংশন এবং__threadPeekMessageআসুন নিচের সহজ উদাহরণটি দেখিঃ

function func1() {
    var id = __threadId()
    while (true) {
        var postMsg = "Message from thread function func1" with "from id:" + id + 
        __threadPostMessage(0, postMsg)              // Send a message to the main thread
        var peekMsg = __threadPeekMessage(0)         // Receive messages from the main thread
        Log(peekMsg)
        Sleep(5000)
    }
}

function main() {
    var threadId = __Thread(func1)
    
    while (true) {
        var postMsg = "Messages from the main function of the main thread"
        __threadPostMessage(threadId, postMsg)
        var peekMsg = __threadPeekMessage(threadId)
        Log(peekMsg, "#FF0000")                     // #FF0000 , Set the log to red for distinction
        Sleep(5000)
    }
}

দ্য__threadPostMessagefunction একটি থ্রেডে একটি বার্তা পাঠাতে ব্যবহৃত হয়। প্রথম প্যারামিটারটি নির্দিষ্ট থ্রেডের আইডি যা পাঠানো হবে এবং দ্বিতীয় প্যারামিটারটি বার্তা পাঠানো হবে, যা একটি স্ট্রিং, একটি মান, একটি অ্যারে, বা একটি JSON অবজেক্ট এবং তাই হতে পারে। বার্তাগুলি সমান্তরাল থ্রেড ফাংশনে মূল থ্রেডে পাঠানো যেতে পারে এবং প্রধান থ্রেডের আইডি 0 হিসাবে সংজ্ঞায়িত করা হয়।

দ্য__threadPeekMessageফাংশন একটি নির্দিষ্ট থ্রেড দ্বারা প্রেরিত বার্তা নিরীক্ষণ করতে ব্যবহৃত হয়। প্রথম প্যারামিটারটি থ্রেডের নির্দিষ্ট আইডি নিরীক্ষণ করা। দ্বিতীয় প্যারামিটারটি টাইমআউট সময় (মিলিসেকেন্ডে) সেট করতে পারে, অথবা এটি -1 এ সেট করা যেতে পারে, যার অর্থ ব্লকিং, এবং এটি একটি বার্তা না হওয়া পর্যন্ত ফিরে আসবে না। আমরা সমান্তরাল থ্রেড ফাংশনে বর্তমান থ্রেডে প্রধান থ্রেড দ্বারা প্রেরিত বার্তাটি শুনতে পারি এবং প্রধান থ্রেডের আইডি 0 হিসাবে সংজ্ঞায়িত করা হয়।

অবশ্যই, প্রধান থ্রেডের সাথে যোগাযোগকারী সমান্তরাল থ্রেড ব্যতীত। সমান্তরাল থ্রেডগুলিও একে অপরের সাথে সরাসরি যোগাযোগ করতে পারে।

সমান্তরাল থ্রেড এক্সিকিউশন ফাংশনে বর্তমান থ্রেড আইডি পান

উপরের উদাহরণে,var id = __threadId()ব্যবহার করা হয়, এবং__threadId()ফাংশন বর্তমান থ্রেডের আইডি পেতে পারে।

ভাগ করা থ্রেডের মধ্যে সংরক্ষিত ভেরিয়েবল

থ্রেডগুলির মধ্যে যোগাযোগের পাশাপাশি, ভাগ করা ভেরিয়েবলগুলি ইন্টারঅ্যাকশনের জন্যও ব্যবহার করা যেতে পারে।

function testFunc() {
    __threadSetData(0, "testFunc", 100)   // Stored in the current thread environment, key-value pair testFunc : 100
    Log("testFunc execution completed")
}

function main() {
    // threadId is 1, the created thread with threadId 1 will be executed first, as long as the thread resources are not reclaimed, the variables stored locally in the thread will be valid
    var testThread = __Thread(testFunc)
    
    Sleep(1000)

    // export in main, get testFunc: 100
    Log("in main, get testFunc:", __threadGetData(testThread, "testFunc"))   // Take out the value whose key name is testFunc
}

উপরের সব ফাংশন একটি সহজ বিক্ষোভ. আসুন একটু জটিল পরীক্ষা উদাহরণ তাকান.

নেটিভ মাল্টি-থ্রেডেড জাভাস্ক্রিপ্ট এবং WASM এর মধ্যে পারফরম্যান্স তুলনা

এই পরীক্ষার কৌশল ঠিকানাঃhttps://www.fmz.com/strategy/401463

এক নজরে, আপনি হয়তো জানেন না যে এই পরীক্ষার কৌশলটি কী করে। এটি কোন ব্যাপার না, আসুন এটি ব্যাখ্যা করি। প্রথমে, আসুন জেনে নেওয়া যাক WASM কি?


Then the test strategy is to compare the execution efficiency of wasm and javascript, but when comparing, the two execution methods can be executed successively, and the time-consuming of each is counted. It is also possible to allow the two execution methods to execute concurrently, and the statistics are time-consuming. Now that the underlying concurrency implementation of the JavaScript language strategy has been supported, the test strategy uses a concurrent method to compare naturally and compare the execution speed of the same algorithm.

- Algorithm of C language version, fib function

// সি ভাষায় ফিবোনাচি সংখ্যার পুনরাবৃত্তিমূলক অ্যালগরিদম int fib ((int f) { if (f < 2) return f; ফেরত fib ((f - 1) + fib ((f - 2); }

- JavaScript language version of the algorithm, fib function

// একই ফিবোনাচি সংখ্যা জন্য একটি পুনরাবৃত্তিমূলক অ্যালগরিদম, জাভাস্ক্রিপ্টে লেখা ফাংশন fib ((f) { যদি (f < 2) ফেরত দেয় f ফেরত fib ((f - 1) + fib ((f - 2) }

It can be seen that the logic of the two fib function algorithms is exactly the same. The following is the source code of the test strategy:

ফাংশন main() { // কোডটি দেখতে সহজ করার জন্য, আমি সরাসরি নিম্নলিখিত কোডটিতে মন্তব্য লিখছিঃ চলুন চক্র = 100 // পরীক্ষা লুপ 100 বার সঞ্চালন let input = 30 // পরামিতি যে অ্যালগরিদম ফাইব ফাংশন পাস করা হবে থ্রেড = [ __Thread(function(cycle, input) { // ফাংশন fib এর জাভাস্ক্রিপ্ট সংস্করণ ব্যবহার করে গণনা সম্পাদন করার জন্য একটি থ্রেড একযোগে তৈরি করা হয় ফাংশন fib ((f) { // পরীক্ষার জন্য ব্যবহৃত নির্দিষ্ট অ্যালগরিদম, ফাংশন fib যদি (f < 2) ফেরত দেয় f ফেরত fib ((f - 1) + fib ((f - 2) } রেট = ০ for (let i = 0; i < cycle; i++) { // 100 বার লুপ ret = fib(input); // জাভাস্ক্রিপ্ট ভাষার fib ফাংশন কল জাভাস্ক্রিপ্টের অগ্রগতি লগঃ , i) } return জাভাস্ক্রিপ্ট ফাইবারঃ + ret }, চক্র, ইনপুট),

    __Thread(function(cycle, input) {           // Run a thread concurrently to perform calculations using the wasm version of the fib function
        let data = 'data:hex,0061736d010000000186808080000160017f017f0382808080000100048480808000017000000583808080000100010681808080000007908080800002066d656d6f727902000366696200000aa480808000019e80808000000240200041024e0d0020000f0b2000417f6a10002000417e6a10006a0b'
        let m = wasm.parseModule(data)          // The data variable is the hex string of the wasm-encoded C language fib function, and the wasm model m is created using wasm.parseModule

        let instance = wasm.buildInstance(m, {  // Model instantiation, allocate a certain stack space
            stack_size: 65 * 1024 * 1024,
        })

        let ret = 0
        for (let i = 0; i < cycle; i++) {                // loop for 100 times 
            ret = instance.callFunction('fib', input)    // Calling the fib function code in the wasm instance is equivalent to calling the int fib(int f) function 
            Log("wasm progress: ", i)
        }

        return 'wasm fib: ' + ret
    }, cycle, input)
]

// The elements in the threads array are the IDs returned by the __Thread function
threads.forEach(function(tid) {
    let info = __threadJoin(tid)                         // Use the __threadJoin function to wait for two concurrent threads to execute and get the execution result
    Log('#'+tid, info.ret, 'elapsed:', info.elapsed / 1e6, "#ff0000")   // output execution result
})

}

Simply put, WASM is a program code with higher execution efficiency. In the example, we convert the c language code of "Fibonacci number recursive algorithm" into WASM. The process is like this:

1. Compile a piece of C language function code into wasm code.

We can use the website to convert: https://wasdk.github.io/WasmFiddle/

// সি ভাষায় ফিবোনাচি সংখ্যার পুনরাবৃত্তিমূলক অ্যালগরিদম int fib ((int f) { if (f < 2) return f; ফেরত fib ((f - 1) + fib ((f - 2); }

2. Further encode the wasm code into a hex string.

The following commands can be used:

python -c print ((data:hex,+bytes.hex)) open ((program.wasm,rb).read)))

The encoded hex string is ```let data = 'data:hex,0061736d0100000001868...``` in the code.

3. Then parse it into a wasm model through the function ```wasm.parseModule()``` integrated by FMZ.

4. Create a wasm model instance through the function ```wasm.buildInstance()``` integrated by FMZ.

5. Then call the ```fib``` function in this wasm model instance, namely: ```ret = instance.callFunction('fib', input)```.

## Create a real bot to run the test
This test strategy can only be used for real bot testing. JavaScript multi-threading functions do not support backtesting so far.

```wasm``` and ```JavaScript``` execution comparison, the final execution results:

২০২৩-০৩-০৬ ১১ঃ০০ঃ৩৩ তথ্য ২ নং বার্তাঃ ৮৩২০৪০ শেষঃ ১৩২৮৩.৭৭৩০১৯ ২০২৩-০৩-০৬ ১১ঃ০০ঃ৩৩ তথ্য ১ম জাভাস্ক্রিপ্ট ফাইবারঃ ৮৩২০৪০ শেষঃ ২১২৬৬.৩২৬৯৭৪ It seems thatwasm` কম সময় নেয় এবং ভাল।


সম্পর্কিত বিষয়বস্তু

আরও দেখুন