首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >尝试为递归函数实现内联Webworker

尝试为递归函数实现内联Webworker
EN

Stack Overflow用户
提问于 2018-04-16 23:44:09
回答 2查看 630关注 0票数 0

我有一个使用Javascript的递归函数的第一个版本,它会产生预期的结果。以下是工作版本:

代码语言: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;
}

从这一点出发,我想使用“内联”WebWorkers将递归专用于WebWorker,并避免在浏览器中挂起进程。

我试着跟踪此链接另一个链接

我不知道是否必须对主线程"postmessage“对象HitCurrent或值eval:通过使用WebWorker,我在return指令(在终端情况下返回一个值)和传递给下一个递归调用的objetHitCurrent参数之间产生了混淆。

如果有人能给出一些线索,通过使用内联webworker (或者使用webworker的经典方式)来复制这个原始算法。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-04-24 06:32:50

内联网络工作者示例:

作为您的代码,没有function evaluationfunction exploreHitLine。在使用以下代码之前,必须将它们插入到code中。

代码语言:javascript
复制
{
    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:

代码语言:javascript
复制
{
    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.

代码语言:javascript
复制
{
    // 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 );
    } );
}

对我错误的解释:

  1. 当处于“严格模式”时,不可能使用"eval“作为变量的名称。

=>

来自:eval

致:evaluated

  1. Worker.postMessage( aMessage, Transferrable ),在本例中,您不需要使用第二个参数。

=>

来自:firstWorker.postMessage( HitTemp, HitTemp.playerCurrent, maxNodes );

致:firstWorker.postMessage( [ HitTemp, HitTemp.playerCurrent, maxNodes ] );

(https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage)

  1. 继续到2,将参数传递给recursiveFunction是固定的。
票数 1
EN

Stack Overflow用户

发布于 2018-04-25 00:52:20

  • eval是一个关键字;使用其他变量名。
  • postMessage只接受一个参数(它也接受一个可转移的,但这不适用于您的情况),如果该参数不是一个原始值,它应该是一个可以序列化的对象(例如,您不能将函数或方法直接传递给web工作者)。

我可能误解了你想要做的事情,但是你可能想重新考虑递归地产生一批不知名的网络工作者!如果您只想释放主堆栈,只需生成一个webworker并将函数的参数传递给它,并在该webworker中同步执行递归计算,而不需要生成一个新的工作人员。产卵太多的网络工作者将消耗大量的资源,实际上会减慢你的计算速度!FYI,产卵每一个新的网络工作者需要40毫秒,并占用资源。这是一个关于使用多线程计算递归函数的一般观察!这可能会有帮助:https://softwareengineering.stackexchange.com/questions/238729/can-recursion-be-done-in-parallel-would-that-make-sense

调用到URL.createObjectURL中的所有函数( new (. ))块,我是否必须将它们包含在这个块中,或者是否可以将它们写到外部(正如您所说的评估和explotHitLine函数)?

您的webworker是一个完全独立的JS文件和执行上下文;您将无法访问在其上下文中未定义的任何内容或将其作为消息发送给它。

顺便说一句,您的代码中有一些错误会阻止它正确编译:infinity应该是InfinityplayerBlackplayerWhite是未定义的,等等。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49867753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档