在 for 循环中高效地打印每 x 次迭代

Efficiently print every x iterations in for loop

我正在编写一个程序,其中某个 for 循环被迭代了很多次。

单次迭代不会花费很长时间,但由于程序如此频繁地迭代循环,因此需要相当长的时间来计算。

为了在不减慢程序速度的情况下获得有关程序进度的更多信息,我想每第 x 步打印一次进度。

是否有不同的方法来执行此操作,而不是像这样使用模数的条件:

for(int i = 0; i < some_large_number; i++){
    if(i % x == 0)
        printf("%f%%\r", percent);
    //some other code
    .
    .
    .
}

?

先谢谢了

我会这样做:

int j = x;
for (int i = 0; i < some_large_number; i++){
    if(--j == 0) {
        printf("%f%%\r", percent);
        j = x;
    }
    //some other code
    .
    .
    .
}

关于您的性能问题的最快方法是使用嵌套循环:

unsigned int x = 6;
unsigned int segments = some_large_number / x; 
unsigned int y;

for ( unsigned int i = 0; i < segments; i++ ) {

    printf("%f%%\r", percent); 

    for ( unsigned int j = 0; j < x; j++ ) {

       /* some code here */

    }
}


// If some_large_number can´t be divided evenly through `x`:

if (( y = (some_large_number % x)) != 0 )
{
    for ( unsigned int i = 0; i < y; i++ ) {

       /* same code as inside of the former inner loop. */

    }
}

另一个示例是使用不同的计数变量进行检查,通过将其与 x - 1 进行比较来执行打印过程,如果匹配则将变量重置为 -1

unsigned int x = 6;
unsigned int some_large_number = 100000000;

for ( unsigned int i = 0, int j = 0; i < some_large_number; i++, j++ ) {

    if(j == (x - 1))
    {
        printf("%f%%\r", percent);
        j = -1;
    }
    /* some code here */
}

将 some_large_number 除以 x。现在循环 x 次并将其与新整数嵌套,然后打印百分比。我的意思是:

int temp = some_large_number/x;
for (int i = 0; i < x; i++){
   for (int j = 0; j < temp; j++){
        //some code
   }
   printf("%f%%\r", percent);
}

此代码:

for(int i = 0; i < some_large_number; i++){
    if(i % x == 0)
        printf("%f%%\r", percent);
    //some other code
    .
    .
    .
}

可以重组为:

/*  Partition the execution into blocks of x iterations, possibly including a
    final fragmentary block.  The expression (some_large_number+(x-1))/x
    calculates some_large_number/x with any fraction rounded up.
*/
for (int block = 0, i = 0; block < (some_large_number+(x-1))/x; ++block)
{
    printf("%f%%\r", percent);

    //  Set limit to the lesser of the end of the current block or some_large_number.
    int limit = (block+1) * x;
    if (some_large_number < limit) limit = some_large_number;

    //  Iterate the original code.
    for (; i < limit; ++i)
    {
        //some other code
    }
}

具有以下注意事项和属性:

  • 内部循环没有比原始循环更多的工作(它没有额外的变量来计算或测试)并且完全删除了 i % x == 0 测试。这对于内部循环来说是最佳的,因为它尽可能减少了名义上的工作量,尽管现实世界的硬件有时会有挑剔的行为,可能导致更多的计算时间而实际工作更少。
  • 引入了新标识符 blocklimit,但可以进行更改以避免与原始代码中的使用发生任何冲突。
  • 除上述之外,内部循环的操作与原始代码相同:它以与原始代码相同的顺序看到相同的 i 值,因此该代码无需更改。
  • some_large_number+(x-1) 可能会溢出 int