如何强制递归函数产生跳帧?
How to force a recursive function to yield skip frames?
如何强制递归函数在 运行 时间产生帧?
我尝试将 yield 函数放在递归函数的不同阶段。
我不明白发生了什么,因为忽略了每 1000 次递归打印时间的 if 条件,它仅大约每 100 万次递归产生和打印一次。 90% 应该被拾取的打印命令被代码忽略并且没有出现。
运行时间仅每 1-2 分钟产生一次,并且一次打印十几个语句。
这是我编写的最快的代码版本;如果我向上或向下更改 yield 语句,运行time 有时会完全冻结并且 10 分钟内没有任何反应。
为什么它会冻结,我该如何更改它?
//A working 3D floodfill function that reads and writes a boolean voxel array:
private var maxAbort = 1000000000;
function boundary( x:int, y:int, z:int ): IEnumerator //floodfill algo
{
if ( read3DboolArray(x,y,z)==false && bcnt<maxAbort){//pprevent Whosebug with limit FASTER
if ( x >= 0 && x < bsizex && y >= 0 && y < bsizey && z >= 0 && z < bsizez)
{
write3DboolArray(x,y,z,true);
boundary(x+1,y,z);
boundary(x-1,y,z); yield WaitForFixedUpdate();
boundary(x,y+1,z);
boundary(x,y-1,z); // yield WaitForFixedUpdate();
boundary(x,y,z+1);
boundary(x,y,z-1);
}
if ( bcnt % 1000== 0 )//mark new start if ended this recursion run
{
print(bcnt+ " ------ " +
(Time.realtimeSinceStartup-tt));
bcnt+=1;
yield WaitForFixedUpdate();
}
} else return;
}
它使用的是 Unity3D 的 MonoDevelop 运行时代,它是 .NET Framework 2.0 的一个分支
在方法中使用 yield 本质上是将方法变成迭代器的构造函数。为了让迭代器真正做一些有意义的事情,你实际上需要迭代它。
boundary(x+1,y,z);
boundary(x-1,y,z); yield WaitForFixedUpdate();
boundary(x,y+1,z);
boundary(x,y-1,z); // yield WaitForFixedUpdate();
boundary(x,y,z+1);
boundary(x,y,z-1);
这基本上只是创建了几个枚举器,然后将它们丢弃。要使递归 yield 起作用,您必须 yield 所有结果一直返回到初始调用站点。
使用 Yield 和协程来处理这种工作负载似乎效率很低。我建议要么尝试将算法重塑为迭代(by using a stack for example,这也有助于解决明显的堆栈溢出问题),要么将其卸载到单独的工作线程中。
如何强制递归函数在 运行 时间产生帧?
我尝试将 yield 函数放在递归函数的不同阶段。
我不明白发生了什么,因为忽略了每 1000 次递归打印时间的 if 条件,它仅大约每 100 万次递归产生和打印一次。 90% 应该被拾取的打印命令被代码忽略并且没有出现。 运行时间仅每 1-2 分钟产生一次,并且一次打印十几个语句。
这是我编写的最快的代码版本;如果我向上或向下更改 yield 语句,运行time 有时会完全冻结并且 10 分钟内没有任何反应。
为什么它会冻结,我该如何更改它?
//A working 3D floodfill function that reads and writes a boolean voxel array:
private var maxAbort = 1000000000;
function boundary( x:int, y:int, z:int ): IEnumerator //floodfill algo
{
if ( read3DboolArray(x,y,z)==false && bcnt<maxAbort){//pprevent Whosebug with limit FASTER
if ( x >= 0 && x < bsizex && y >= 0 && y < bsizey && z >= 0 && z < bsizez)
{
write3DboolArray(x,y,z,true);
boundary(x+1,y,z);
boundary(x-1,y,z); yield WaitForFixedUpdate();
boundary(x,y+1,z);
boundary(x,y-1,z); // yield WaitForFixedUpdate();
boundary(x,y,z+1);
boundary(x,y,z-1);
}
if ( bcnt % 1000== 0 )//mark new start if ended this recursion run
{
print(bcnt+ " ------ " +
(Time.realtimeSinceStartup-tt));
bcnt+=1;
yield WaitForFixedUpdate();
}
} else return;
}
它使用的是 Unity3D 的 MonoDevelop 运行时代,它是 .NET Framework 2.0 的一个分支
在方法中使用 yield 本质上是将方法变成迭代器的构造函数。为了让迭代器真正做一些有意义的事情,你实际上需要迭代它。
boundary(x+1,y,z);
boundary(x-1,y,z); yield WaitForFixedUpdate();
boundary(x,y+1,z);
boundary(x,y-1,z); // yield WaitForFixedUpdate();
boundary(x,y,z+1);
boundary(x,y,z-1);
这基本上只是创建了几个枚举器,然后将它们丢弃。要使递归 yield 起作用,您必须 yield 所有结果一直返回到初始调用站点。
使用 Yield 和协程来处理这种工作负载似乎效率很低。我建议要么尝试将算法重塑为迭代(by using a stack for example,这也有助于解决明显的堆栈溢出问题),要么将其卸载到单独的工作线程中。