Эффективно печатать каждые x итераций цикла for - PullRequest
4 голосов
/ 29 апреля 2020

Я пишу программу, в которой определенный for-l oop повторяется много раз.

Одна итерация не занимает много времени, но поскольку программа повторяет l oop так часто вычисление занимает довольно много времени.

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

Есть ли другой способ сделать это, кроме условного выражения по модулю, например:

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

?

Спасибо, заранее

Ответы [ 4 ]

2 голосов
/ 29 апреля 2020

Этот код:

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
    }
}

Со следующими оговорками и свойствами:

  • Внутренняя l oop не имеет больше работы, чем исходный l oop (у него нет дополнительной переменной для подсчета или проверки), и тест i % x == 0 полностью удален. Это оптимально для внутреннего l oop в том смысле, что оно максимально сокращает номинальный объем работы, хотя в реальных аппаратных средствах иногда есть привередливые поведения, которые могут привести к увеличению времени вычислений для менее реальной работы.
  • Новые идентификаторы block и limit введены, но могут быть изменены, чтобы избежать любых конфликтов с использованием в исходном коде.
  • Кроме вышеперечисленного, внутренний l oop работает идентично оригиналу код: он видит те же значения i в том же порядке, что и исходный код, поэтому никаких изменений в этом коде не требуется.
  • some_large_number+(x-1) может переполниться int.
2 голосов
/ 29 апреля 2020

Самый быстрый подход к вашей проблеме производительности - использовать вложенную l oop:

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 */
}
2 голосов
/ 29 апреля 2020

Разделите some_large_number на x. Теперь l oop для 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);
}
2 голосов
/ 29 апреля 2020

Я бы сделал это так:

int j = x;
for (int i = 0; i < some_large_number; i++){
    if(--j == 0) {
        printf("%f%%\r", percent);
        j = x;
    }
    //some other code
    .
    .
    .
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...