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

Efficient way to skip code every X iterations?

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

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

为了效率,我想 运行 每 X 步只编写一些代码。

if step mod 60 {

}

会 运行 每 60 步(或 60 fps 时 1 秒)阻塞一次。

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

可能涉及按位运算符?

我知道这适用于所有其他帧:

// Declare
counter = 0

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

if counter {

}

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

本质上:

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

采用 modulus 并基于它进行切换的变体称为 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%,那几乎可以肯定你应该考虑更大的加速。

但是,如果循环速度很快,您可以这样输入:

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

在某些硬件中,该测试归结为一条指令递减和分支如果为负。