每X次迭代跳过代码的有效方法是什么?

时间:2015-10-02 19:32:47

标签: performance time modulus processing-efficiency

我正在使用GameMaker Studio,您可以将其视为一个巨大的循环。

我使用计数器变量step来跟踪它是什么帧。

为了提高效率,我希望每隔一个步骤运行一些代码。

if step mod 60 {

}

每60步(或以60 fps为1秒)运行该块。

我的理解是模数是一个繁重的操作,但我想象计算可能会失控。有没有更有效的方法来做到这一点?

也许涉及按位运算符?

我知道这可以适用于所有其他框架:

// Declare
counter = 0

// Step
counter = (counter + 1) & 1

if counter {

}

或者即使数字很大,模数对60FPS的性能影响也可以忽略不计?

2 个答案:

答案 0 :(得分:3)

本质上:

i := 0
WHILE i < n/4
  do rest of stuff × 4
  do stuff that you want to do one time in four
  Increment i

Do rest of stuff i%4 times

这个变量采用模数和基于它的开关,称为Duff的设备。哪个更快将取决于您的架构:在许多RISC芯片上,mod在单个时钟周期内执行,但在其他CPU上,整数除法甚至可能不是本机指令。

如果您本身没有循环计数器,因为它是一个事件循环,例如,您可以在执行代码的if块中每隔四次重置一次并重置它:

i := 1
WHILE you loop
  do other stuff
  if i == 4
    do stuff
    i := 1
  else
    i := i + 1

这是一个例子,两次做一些东西,三次做一次:

WHILE looping
  do stuff
  do stuff a second time
  do stuff B
  do stuff a third time
  do stuff C
  do stuff a fourth time
  do stuff B
  do stuff a fifth time
  do stuff a sixth time
  do stuff B
  do stiff C

请注意,您所做的事情可能包括调用一次事件循环。

由于这可能变得难以处理,您可以使用模板元编程在C ++中为您编写这些循环,如:

constexpr unsigned a = 5, b = 7, LCM_A_B = 35;

template<unsigned N>
  inline void do_stuff(void)
{
  do_stuff_always();
  if (N%a)
    do_stuff_a(); // Since N is a compile-time constant, the compiler does not have to check this at runtime!

  if (N%b)
    do_stuff_b();

  do_stuff<N-1>();
}

template<>
  inline void do_stuff<1U>(void)
{
  do_stuff_always();
}

while (sentinel)
  do_stuff<LCM_A_B>(); 

但是,一般情况下,如果您想了解优化是否有帮助,请进行分析。

答案 1 :(得分:2)

答案中最重要的部分是:在上下文中,测试可能花费的时间非常少,以至于不值得离开大脑的离子来思考它。 如果它只花费1%,几乎可以肯定你应该考虑更大的加速比。

但是,如果循环很快,你可以输入这样的东西:

if (--count < 0){
  count = 59;
  // do your thing
}

在某些硬件中,该测试归结为单个指令递减和分支 - 如果否定。