我有一个带有长循环的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%的运行时间,非常重要!
答案 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秒