问题描述
我希望基于所包含的代码中的嵌套循环加快测试所有组合的过程。
我目前在Windows 10上仍然使用JavaScript和NodeJS。
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和/或cluster模块来分散工作。 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];
let params = [...initialParams]
const maxValue = [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;
}
}