C ++打印进度,对运行时影响最小

时间:2015-08-12 13:26:05

标签: c++ console progress

我有一个带有长循环的C ++程序。它有大约500000次迭代。 我想每5%打印一次进度。

到目前为止我的内容如下。 问题在于它会一遍又一遍地写同一行(0%,%5等)。这是因为在将百分比截断为整数之后,将有1000次迭代将达到5的倍数。这使得程序明显变慢。

相反,如果我没有截断为整数,那么percent % 5.0的结果不可能精确为0.

如何打印进度指示器,尽可能减少对运行时间的影响?

// Counters for progress indicator
int i = 0;
float totalWindows = (float)(win.nX * win.nY);
int percent;

while (win.next() == 0)
{
    // Read the data

    // Nicely formatted progress indicator
    i++;
    percent = (i / totalWindows) * 100;
    if (percent % 5 == 0)
    {
        std::cout << "\r" << std::string(percent/5, '|') << percent << "%";
        std::cout.flush();
    }



}

编辑: 谢谢你的回答。我已经和christophes一起去了,其中只有最少的指令。 它削减了25%的运行时间,非常重要!

3 个答案:

答案 0 :(得分:2)

考虑到public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) { if (operation.parameters == null) return; IDictionary<string, object> parameterValuePairs = GetParameterValuePairs(apiDescription.ActionDescriptor); foreach (var param in operation.parameters) { if (param.schema != null && param.schema.@ref != null) { string schemaName = param.schema.@ref.Split('/').LastOrDefault(); if (schemaRegistry.Definitions.ContainsKey(schemaName)) foreach (var props in schemaRegistry.Definitions[schemaName].properties) { if (parameterValuePairs.ContainsKey(props.Key)) props.Value.@default = parameterValuePairs[props.Key]; } } var parameterValuePair = parameterValuePairs.FirstOrDefault(p => p.Key.IndexOf(param.name, StringComparison.InvariantCultureIgnoreCase) >= 0); param.@default = parameterValuePair.Value; } } 似乎保持不变,并且totalWindows递增/递减可能比转换为int的许多integer操作更快,我建议:

double

如果您担心累积舍入对于显示进度是不可接受的,您可以选择计算// Counters for progress indicator int i = 0; float totalWindows = (float)(win.nX * win.nY); int increment5 = 0.05 * totalWindows; // how many iterations does 5% represent ? int countdown = increment5; // decrement countdown instead of modulo int percent5 = 0; // number of elements in the progress bar (1 means 5%) while (win.next() == 0) { // Read the data // Nicely formatted progress indicator i++; if (--countdown == 0) { percent5++; std::cout << "\r" << std::string(percent5, '|') << percent5*5 << "%"; countdown = increment5; std::cout.flush(); } } - 块中的确切值:计算将每5%执行一次,而不是在每次迭代。

答案 1 :(得分:1)

怎么样:

int step = 5;
int nextPrint = step;

while (win.next() == 0)
{
    // Read the data

    // Nicely formatted progress indicator
    i++;
    percent = (100 * i) / totalWindows;
    if (percent >= nextPrint)
    {
        std::cout << "\r" << std::string(percent/5, '|') << percent << "%";
        std::cout.flush();
        nextPrint += step;
    }
}

顺便说一句: 为什么你将totalWindows作为浮点数?这也会伤害表现。如果迭代次数为500000,那么32位int就足够了。

另一种更好的方法,因为在每个循环中都没有计算百分比:

const int percentPrint = 5;
int step = totalWindows / (100/percentPrint);
int nextPrint = step;

while (win.next() == 0)
{
    // Read the data

    // Nicely formatted progress indicator
    i++;
    if (i >= nextPrint)
    {
        percent = (100 * i) / totalWindows;
        std::cout << "\r" << std::string(percent/percentPrint , '|') << percent << "%";
        std::cout.flush();
        nextPrint += step;
    }
}
std::cout << "\r" << std::string(100/percentPrint , '|') << percent << "%";
std::cout.flush();

答案 2 :(得分:0)

不是每次计算百分比,而是计算总数的5%,并直接使用它。

考虑这个简化的例子:

int main(int argc, char * argv) {
  int total = 50000;
  int total_percent_stop = total * 5 / 100; //Set the percentage here.

  for (int i = 0; i < total; i++) {
    if (i % total_percent_stop == 0) {
      printf("%d percent done\n", (i / total_percent_stop) * 5);
    }
  }
}

如果此特定代码的性能对您非常重要,您可以通过执行此类操作(以牺牲一些可读性为代价)来避免相对昂贵的除法操作。

int main(int argc, char * argv) {
  int total = 50000;
  int total_percent_stop = total * 5 / 100; //Set the percentage here

  for (int i = 0, percent_counter = 0, n_percent = 0;
       i < total;
       i++, percent_counter++) {
    if (percent_counter == total_percent_stop) {
      percent_counter = 0;
      n_percent++;
      printf("%d percent done\n", n_percent * 5);
    }
  }
}

在我的机器上,对于足够大的总值,第二个明显更快。当我将所有内容更改为无符号长多数并将总数设置为50亿时,第二次占用9.336秒,第一次占用40.159秒