我有一个使用Javascript的递归函数的第一个版本,它产生预期的结果。低于工作版本:
// Call the recursive function and get final (a,b) results
var HitTemp = JSON.parse(JSON.stringify(HitCurrent));
var result= recursiveFunction(HitTemp, HitTemp.playerCurrent, maxNodes);
var a = HitTemp.coordPlayable[0];
var b = HitTemp.coordPlayable[1];
// Recursive function
function recursiveFunction(HitCurrent, colorCurrent, depth) {
// Indices
var i, j, k;
// Evaluation
var arrayTemp, eval, e;
// Set current color to HitCurrent
HitCurrent.playerCurrent = colorCurrent;
// Deep copy of arrayCurrent array
arrayTemp = JSON.parse(JSON.stringify(HitCurrent.arrayCurrent));
// If depth equal to 0
if (depth == 0)
return evaluation(HitCurrent);
// Starting evaluation
eval = -infinity;
// Browse all possible hits
for (i = 0; i < 8; i++)
for (j = 0; j < 8; j++) {
if (HitCurrent.arrayPlayable[i][j] == 'playable') {
for (k = 0; k < 8; k++) {
// Explore line started from (i,j) with direction "k"
exploreHitLine(HitCurrent, i, j, k, 'drawing');
}
// Recursive call
e = recursiveFunction(JSON.parse(JSON.stringify(HitCurrent)), ((JSON.stringify(HitCurrent.playerCurrent) == JSON.stringify(playerBlack)) ? playerWhite : playerBlack), depth-1);
if (e > eval) {
HitCurrent.coordPlayable = [i,j];
eval = e;
}
}
// Restore arrayCurrent array
HitCurrent.arrayCurrent = JSON.parse(JSON.stringify(arrayTemp));
}
return eval;
}
由此,我想使用&#34; inline&#34; WebWorkers将递归专用于WebWorker并避免在浏览器中挂起进程。
我尝试关注this link和this other link
我不知道我是否需要&#34; postmessage
&#34;主线程的对象HitCurrent
或值eval
:通过使用WebWorker,我在return
指令(返回终端案例中的值)和objet {{}之间产生混淆1}}参数传递给下一个递归调用。
如果有人可以通过使用内联网络工程师(或使用经典的网络工作方式)提供一些线索来重现这个原始算法。
答案 0 :(得分:1)
内联webworker示例:
作为您的代码,没有function evaluation
,function exploreHitLine
。
在使用以下代码之前,您必须将它们插入code
。
{
let workerScript = URL.createObjectURL( new Blob( [ `
"use strict";
// Recursive function
function recursiveFunction( HitCurrent, colorCurrent, depth ) {
// Indices
var i, j, k;
// Evaluation
var arrayTemp, eval, e;
// Set current color to HitCurrent
HitCurrent.playerCurrent = colorCurrent;
// Deep copy of arrayCurrent array
arrayTemp = JSON.parse(JSON.stringify(HitCurrent.arrayCurrent));
// If depth equal to 0
if ( depth === 0 ) return evaluation(HitCurrent);
// Starting evaluation
eval = -infinity;
// Browse all possible hits
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
if (HitCurrent.arrayPlayable[i][j] === 'playable') {
for (k = 0; k < 8; k++) {
// Explore line started from (i,j) with direction "k"
exploreHitLine(HitCurrent, i, j, k, 'drawing');
}
// Recursive call
e = recursiveFunction(JSON.parse(JSON.stringify(HitCurrent)), ((JSON.stringify(HitCurrent.playerCurrent) == JSON.stringify(playerBlack)) ? playerWhite : playerBlack), depth-1);
if (e > eval) {
HitCurrent.coordPlayable = [i,j];
eval = e;
}
}
// Restore arrayCurrent array
HitCurrent.arrayCurrent = JSON.parse(JSON.stringify(arrayTemp));
}
}
return eval;
}
onmessage = function ( event ) {
let params = event.data;
postMessage( { result: recursiveFunction( ...params ) } );
}
` ], { type: "plain/text" } ) );
// Call the recursive function and get final (a,b) results
new Promise( resolve => {
let HitTemp = JSON.parse(JSON.stringify(HitCurrent));
let firstWorker = new Worker( workerScript );
firstWorker.onmessage = function ( event ) {
resolve( event.data ); //{ result: XXX }
}
firstWorker.postMessage( HitTemp, HitTemp.playerCurrent, maxNodes );
} ).then( ( { result } ) => {
let [ a, b ] = result.coordPlayable;
console.log( result );
} );
}
此外,以下是使用内联WebWorker:
{
let workerScript = URL.createObjectURL( new Blob( [ `
"use strict";
onmessage = function ( event ) {
let sum = 0, count = event.data;
for ( let i = 0; i < count**count; i++ ) {
sum += i;
}
postMessage( { result: sum, count } );
}
` ], { type: "plain/text" } ) );
let firstWorker = new Worker( workerScript );
let firstAlive = setTimeout( () => {
firstWorker.terminate();
console.log( "terminated" );
}, 3000 );
firstWorker.onmessage = function ( event ) {
clearTimeout( firstAlive );
console.log( event.data );
}
firstWorker.postMessage( 10 );
let secondWorker = new Worker( workerScript );
let secondAlive = setTimeout( () => {
secondWorker.terminate();
console.log( "terminated" );
}, 3000 );
secondWorker.onmessage = function ( event ) {
clearTimeout( secondAlive );
console.log( event.data );
}
secondWorker.postMessage( 5 );
}
更新1。
{
// Inline webworker version
let workerScript = URL.createObjectURL( new Blob( [ `
"use strict";
// Recursive function
function recursiveFunction( HitCurrent, colorCurrent, depth ) {
// Indices
var i, j, k;
// Evaluation
var arrayTemp, evaluated, e;
// Set current color to HitCurrent
HitCurrent.playerCurrent = colorCurrent;
// Deep copy of arrayCurrent array
arrayTemp = JSON.parse(JSON.stringify(HitCurrent.arrayCurrent));
// If depth equal to 0
if (depth == 0)
return evaluation(HitCurrent);
// Starting evaluation
evaluated = -infinity;
// Browse all possible hits
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
if (HitCurrent.arrayPlayable[i][j] == 'playable') {
for (k = 0; k < 8; k++) {
// Explore line started from (i,j) with direction "k"
exploreHitLine(HitCurrent, i, j, k, 'drawing');
}
// Recursive call
e = recursiveFunction(JSON.parse(JSON.stringify(HitCurrent)), ((JSON.stringify(HitCurrent.playerCurrent) == JSON.stringify(playerBlack)) ? playerWhite : playerBlack), depth-1);
if ( e > evaluated ) {
HitCurrent.coordPlayable = [i,j];
evaluated = e;
}
if (e == -infinity) { HitCurrent.coordPlayable = [ i, j ]; }
// Restore arrayCurrent array
HitCurrent.arrayCurrent = JSON.parse(JSON.stringify(arrayTemp));
}
}
}
return evaluated;
}
onmessage = function ( event ) {
let params = event.data;
//postMessage( { result: recursiveFunction( HitCurrent, HitCurrent.playerCurrent, maxNodes ) } );
postMessage( { result: recursiveFunction( ...params ) } );
};
` ], { type: "plain/text" } ) );
// Call the recursive function and get final (a,b) results
new Promise( resolve => {
let HitTemp = JSON.parse(JSON.stringify(HitCurrent));
let firstWorker = new Worker( workerScript );
firstWorker.onmessage = function ( event ) {
resolve( event.data ); //{ result: XXX }
}
firstWorker.postMessage( [ HitTemp, HitTemp.playerCurrent, maxNodes ] );
} ).then( ( { result } ) => {
let [ a, b ] = result.coordPlayable;
console.log( result );
} );
}
我的错误解释:
=&GT;
来自:eval
至:evaluated
Worker.postMessage( aMessage, Transferrable )
,在这种情况下,您不需要使用第二个参数。=&GT;
来自:firstWorker.postMessage( HitTemp, HitTemp.playerCurrent, maxNodes );
至:firstWorker.postMessage( [ HitTemp, HitTemp.playerCurrent, maxNodes ] );
(https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage)
答案 1 :(得分:0)
eval
是一个关键字;使用其他变量名称。 postMessage
接受一个参数(它也接受一个transferable,但这不适用于你的情况),如果那个参数不是一个原始值,它应该
是一个可序列化的对象(例如,你不能传递函数
或直接向网络工作者的方法)我可能误解了你想要做的事情,但你可能想重新考虑递归地产生未知的数量的网络工作者!只需生成一个 webworker并将函数的参数传递给它,并在该webworker内同步执行递归计算,而不需要生成新的worker,如果你只想释放主堆栈。产生过多的网络工作者将消耗大量资源,实际上会减慢你的计算速度!仅供参考,产生每个新的网络工作者需要大约40毫秒并占用资源。这是关于利用多线程计算递归函数的一般观察!这可能有所帮助: https://softwareengineering.stackexchange.com/questions/238729/can-recursion-be-done-in-parallel-would-that-make-sense
关于调用URL.createObjectURL(new Blob(...))块的所有函数,我是否必须将它们包含在此块中,或者我可以将它们写在它之外(正如您所说的评估和explotHitLine函数)?
您的webworker是一个完全独立的JS文件和执行上下文;您将无法访问未在其上下文中定义的任何内容或作为消息发送给它。
顺便说一下,您的代码中存在一些错误,无法正确编译:{{1}}应该是infinity
,Infinity
和playerBlack
未定义,等等