簡體   English   中英

有沒有比使用嵌套循環更好的尋找解決方案的方法?

[英]Is there a better way of finding solution than using nested loops?

我希望根據包含的代碼段中的嵌套循環加快測試所有組合的過程。

我目前在 JavaScript 和 Windows 10 上使用 NodeJS。

有沒有辦法使用 GPU 而不是 CPU 來計算這個?

var simulations = 0;
for (let i = 10; i <= 20; i++) {
    breakStepThree = i;
    for (let i = 8; i <= 12; i++) {
        historyLevelThree = i;
        for (let i = 0; i <= 60; i += 5) {
            rateLevelThree = i;
            for (let i = 10; i <= 16; i++) {
                breakStepTwo = i;
                for (let i = 6; i <= 10; i++) {
                    historyLevelTwo = i;
                    for (let i = 0; i <= 50; i += 5) {
                        rateLevelTwo = i;
                        for (let i = 10; i <= 14; i++) {
                            breakStepOne = i;
                            for (let i = 4; i <= 8; i++) {
                                historyLevelOne = i;
                                for (let i = 0; i <= 40; i += 5) {
                                    rateLevelOne = i;
                                    simulations++;
                                    console.log('testing combination '
                                        + rateLevelOne + ' ' + historyLevelOne + ' ' + breakStepOne + ' '
                                        + rateLevelTwo + ' ' + historyLevelTwo + ' ' + breakStepTwo + ' '
                                        + rateLevelThree + ' ' + historyLevelThree + ' ' + breakStepThree
                                    );
                                    console.log('performing test no ' + simulations);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

盡我所能實施工作線程。

const {
    Worker, isMainThread, parentPort, workerData
} = require('worker_threads');

const os = require('os');

if (isMainThread) {
    const startTime = Date.now();

    const workers = [];

    // const numberOfThreads = 1;
    const numberOfThreads = os.cpus().length;

    let completed = 0;

    let minBreakStep = 10;
    let maxBreakStep = 20;
    let minMaxElements = [];

    for (let i = minBreakStep; i <= maxBreakStep; i++) {
        minMaxElements.push(i);
    }

    const numberOfElements = minMaxElements.length;

    const numElementsPerThread = Math.ceil(numberOfElements / numberOfThreads);

    let workerIndex = 0;

    let allSimulations = 0;

    for (let i = minBreakStep; i <= maxBreakStep; i += numElementsPerThread) {
        let workerStart = i;
        let workerEnd = i + numElementsPerThread - 1;
        if (workerEnd > maxBreakStep) {
            workerEnd = maxBreakStep
        }

        const worker = new Worker(__filename, {
            workerData: {
                workerIndex,
                workerStart,
                workerEnd,
            }
        });

        worker.on('message', (message) => {
            if (message.completed) {
                completed++;
                console.log('worker ' + message.workerIndex + ' completed ' + message.simulations + ' simulations.');
                allSimulations += message.simulations;
            }
            if (completed === workers.length) {
                console.log('Completed all ' + allSimulations + ' done!');
                const endTime = Date.now();
                const elapsedTime = (endTime - startTime) / 1000;
                console.log(elapsedTime + ' second(s) to complete');
            }
        });
        workerIndex++;
        workers.push(worker);
    }

} else {

    let workerIndex = workerData.workerIndex;
    let workerStart = workerData.workerStart;
    let workerEnd = workerData.workerEnd;

    let simulations = 0;

    for (let i = workerStart; i <= workerEnd; i++) {
        breakStepThree = i;
        for (let i = 8; i <= 12; i++) {
            historyLevelThree = i;
            for (let i = 0; i <= 60; i += 5) {
                rateLevelThree = i;
                for (let i = 10; i <= 16; i++) {
                    breakStepTwo = i;
                    for (let i = 6; i <= 10; i++) {
                        historyLevelTwo = i;
                        for (let i = 0; i <= 50; i += 5) {
                            rateLevelTwo = i;
                            for (let i = 10; i <= 14; i++) {
                                breakStepOne = i;
                                for (let i = 4; i <= 8; i++) {
                                    historyLevelOne = i;
                                    for (let i = 0; i <= 40; i += 5) {
                                        rateLevelOne = i;
                                        simulations++;
                                        // console.log('testing combination '
                                        //     + rateLevelOne + ' ' + historyLevelOne + ' ' + breakStepOne + ' '
                                        //     + rateLevelTwo + ' ' + historyLevelTwo + ' ' + breakStepTwo + ' '
                                        //     + rateLevelThree + ' ' + historyLevelThree + ' ' + breakStepThree
                                        // );
                                        // console.log('performing test no ' + simulations);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    console.log('testing completed');
    parentPort.postMessage({
        completed: true,
        workerIndex: workerIndex,
        simulations: simulations,
    });
}

在 Node.js 中,我不知道 GPU 有什么好用的。根據測試每個組合的工作性質和主機系統的特性,您可以使用內置的worker_threads和/或集群模塊來展開工作。 worker_threads模塊在進程中創建線程。 cluster模塊創建單獨的進程。

盡我所能實施工作線程。

const {
    Worker, isMainThread, parentPort, workerData
} = require('worker_threads');

const os = require('os');

if (isMainThread) {
    const startTime = Date.now();

    const workers = [];

    // const numberOfThreads = 1;
    const numberOfThreads = os.cpus().length;

    let completed = 0;

    let minBreakStep = 10;
    let maxBreakStep = 20;
    let minMaxElements = [];

    for (let i = minBreakStep; i <= maxBreakStep; i++) {
        minMaxElements.push(i);
    }

    const numberOfElements = minMaxElements.length;

    const numElementsPerThread = Math.ceil(numberOfElements / numberOfThreads);

    let workerIndex = 0;

    let allSimulations = 0;

    for (let i = minBreakStep; i <= maxBreakStep; i += numElementsPerThread) {
        let workerStart = i;
        let workerEnd = i + numElementsPerThread - 1;
        if (workerEnd > maxBreakStep) {
            workerEnd = maxBreakStep
        }

        const worker = new Worker(__filename, {
            workerData: {
                workerIndex,
                workerStart,
                workerEnd,
            }
        });

        worker.on('message', (message) => {
            if (message.completed) {
                completed++;
                console.log('worker ' + message.workerIndex + ' completed ' + message.simulations + ' simulations.');
                allSimulations += message.simulations;
            }
            if (completed === workers.length) {
                console.log('Completed all ' + allSimulations + ' done!');
                const endTime = Date.now();
                const elapsedTime = (endTime - startTime) / 1000;
                console.log(elapsedTime + ' second(s) to complete');
            }
        });
        workerIndex++;
        workers.push(worker);
    }

} else {

    let workerIndex = workerData.workerIndex;
    let workerStart = workerData.workerStart;
    let workerEnd = workerData.workerEnd;

    let simulations = 0;

    for (let i = workerStart; i <= workerEnd; i++) {
        breakStepThree = i;
        for (let i = 8; i <= 12; i++) {
            historyLevelThree = i;
            for (let i = 0; i <= 60; i += 5) {
                rateLevelThree = i;
                for (let i = 10; i <= 16; i++) {
                    breakStepTwo = i;
                    for (let i = 6; i <= 10; i++) {
                        historyLevelTwo = i;
                        for (let i = 0; i <= 50; i += 5) {
                            rateLevelTwo = i;
                            for (let i = 10; i <= 14; i++) {
                                breakStepOne = i;
                                for (let i = 4; i <= 8; i++) {
                                    historyLevelOne = i;
                                    for (let i = 0; i <= 40; i += 5) {
                                        rateLevelOne = i;
                                        simulations++;
                                        // console.log('testing combination '
                                        //     + rateLevelOne + ' ' + historyLevelOne + ' ' + breakStepOne + ' '
                                        //     + rateLevelTwo + ' ' + historyLevelTwo + ' ' + breakStepTwo + ' '
                                        //     + rateLevelThree + ' ' + historyLevelThree + ' ' + breakStepThree
                                        // );
                                        // console.log('performing test no ' + simulations);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    console.log('testing completed');
    parentPort.postMessage({
        completed: true,
        workerIndex: workerIndex,
        simulations: simulations,
    });
}

例如,您可以使用 CUDA 綁定對 GPU 執行計算。也許在這種情況下,連接 C 程序並導入/導出實驗設計和結果會更好。 https://github.com/kashif/node-cuda / https://www.npmjs.com/package/cuda-node.js

此外,我將使用如下所示的方法擺脫所有這些嵌套循環。 為了性能起見,可能會去掉切片,並檢查參數,因為下面的幾行只是為了理解這個想法。

class ExperimentGenerator{

  let pointer = 0;
  const initialParams = [0,0,0,0,0,0,0,0];
  let params = [...initialParams]
  const maxValue = [10,10,10,10,10,10,10,10]

  nextExperiment = () =>{
     if(params[pointer] >= maxValue[pointer]){
         pointer++;
         //Reset all other parameters
         params = [initialParams.slice(0,pointer),params[pointer],initialParams.slice(pointer)];
     }
     params[pointer]++;
     return params;
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM