2017-02-14 7 views
0

Как заставить рекурсивную функцию выводить фреймы во время выполнения?Как заставить рекурсивную функцию получить пропущенные рамки?

Я попытался разместить функции выхода на разных этапах рекурсивной функции.

Я не понимаю, что происходит, потому что условие if для печати времени каждые 1000 рекурсий игнорируется, и оно только дает и печатает примерно каждые 1 млн рекурсий. 90% команд печати, которые должны быть подняты, игнорируются кодом и не отображаются. Время выполнения работает только каждые 1-2 минуты и одновременно печатает дюжину операторов.

Это самая быстрая версия кода, который мне удалось написать; если я изменяю оператор yield вверх или вниз, время выполнения иногда полностью зависает, и ничего не происходит в течение 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 stackoverflow 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; 
} 

Она использует среду исполнения MonoDevelop из Unity3D, который является вилка .NET Framework 2.0

+0

Я решил это методом лучше, чем общий стек, вот результат https://unity3dmc.blogspot.fr/2017/02/ultimate-3d-floodfill-scanline.html –

ответ

2

Используя выход в способе по существу превращает метод в конструктор для итератора. Чтобы итератор действительно сделал что-то значимое, вам действительно нужно перебирать его.

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); 

Это в основном просто создает несколько счетчиков, а затем отбрасывает их. Для рекурсивного выхода на работу вам придется полностью вернуть все результаты на начальный сайт вызова.

Выполнение этого с использованием выходных данных и коррекций для такого рода рабочих нагрузок кажется очень неэффективным. Я предлагаю либо попытаться перестроить алгоритм как итеративный (by using a stack for example, что также поможет с вашими явными проблемами переполнения стека), или разгрузить его в отдельный рабочий поток.

+0

Спасибо, я нашел несколько полезных советов от эта итеративная версия. Вероятно, это будет действовать на определенном этапе. на данный момент рекурсивная версия может делать 60 млн. вокселей, и я просто запускаю версию на вокселе на 600 млн., только потому, что она очень медленная. будет [pst некоторый лучший 3D код заливки, когда я его написал. –

Смежные вопросы