我已经使用 cachegrind 在 Linux 上分析了一个计算量很大的 C++ 程序。令人惊讶的是,我的程序的瓶颈并不在于任何排序或计算方法......它在于读取输入。
这是 cachegrind 的屏幕截图,以防我误解了探查器结果(请参阅 scanf()
):
我希望我的说法是正确的,这scanf()
占用了我运行时间的 80.92%。
我使用 读取输入cin >> int_variable_here
,如下所示:
std::ios_base::sync_with_stdio (false); // Supposedly makes I/O faster
cin >> NumberOfCities;
cin >> NumberOfOldRoads;
Roads = new Road[NumberOfOldRoads];
for (int i = 0; i < NumberOfOldRoads; i++)
{
int cityA, cityB, length;
cin >> cityA;
//scanf("%d", &cityA); // scanf() and cin are both too slow
cin >> cityB;
//scanf("%d", &cityB);
cin >> length;
//scanf("%d", &length);
Roads[i] = Road(cityA, cityB, length);
}
如果您没有发现此输入读取代码有任何问题,您能否推荐一种更快的读取输入的方法?我正在考虑尝试getline()
(在等待回复的同时进行处理)。我的猜测是 getline() 可能运行得更快,因为它必须进行更少的转换并且它解析流的总次数更少(只是我的猜测,尽管我最终也必须将字符串解析为整数)。
我所说的“太慢”的意思是,这是一个更大的家庭作业的一部分,它在一段时间后超时(我相信它是 90 秒)。我非常有信心瓶颈就在这里,因为我故意注释掉了我程序其余部分的主要部分,但它仍然超时。我不知道讲师在我的程序中运行了哪些测试用例,但它一定是一个巨大的输入文件。那么,我可以用什么来最快地读取输入?
输入格式是严格的:每行用一个空格分隔的 3 个整数,对于多行:
样本输入:
7 8 3
7 9 2
8 9 1
0 1 28
0 5 10
1 2 16
我需要Road
从每一行中的整数中取出一个。
另外请不要将输入重定向到我的程序到标准输入(myprogram < whatever_test_case.txt
)。我没有阅读特定的文件。我刚从cin
.
更新
使用Slava 的方法:
输入读取似乎花费的时间更少,但它仍然超时(可能不再是由于输入读取)。Slava的方法在Road() ctor
(2下main
)中实现。所以现在它需要 22% 的时间,而不是 80%。我正在考虑优化SortRoadsComparator()
,因为它被称为 26,000,000 次。
比较器代码:
// The complexity is sort of required for the whole min() max(), based off assignment instructions
bool SortRoadsComparator(const Road& a, const Road& b)
{
if (a.Length > b.Length)
return false;
else if (b.Length > a.Length)
return true;
else
{
// Non-determinism case
return ( (min(a.CityA, a.CityB) < min(b.CityA, b.CityB)) ||
(
(min(a.CityA, a.CityB) == min(b.CityA, b.CityB)) && max(a.CityA, a.CityB) < max(b.CityA, b.CityB)
)
);
}
}
使用enhzflep 的方法
考虑解决
我将考虑解决这个问题,因为瓶颈不再是读取输入。Slava 的方法对我来说是最快的。