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 秒だと思います) 後にタイムアウトになる大きな宿題の一部であることを意味します。プログラムの残りの大部分を意図的にコメントアウトしましたが、それでもタイムアウトしたため、ボトルネックがここにあると確信しています。インストラクターが私のプログラムで実行するテスト ケースはわかりませんが、巨大な入力ファイルである必要があります。では、入力を最速で読み取るには何を使用すればよいでしょうか?
入力形式は厳密です: 行ごとに 1 つのスペースで区切られた 3 つの整数、多くの行の場合:
サンプル入力:
7 8 3
7 9 2
8 9 1
0 1 28
0 5 10
1 2 16
Road
各行の整数からa を作成する必要があります。
また、私のプログラムでは、入力が標準入力 ( myprogram < whatever_test_case.txt
) にリダイレクトされることに注意してください。特定のファイルを読んでいません。から読んだところcin
です。
アップデート
スラバの方法を使用する:
入力の読み取りにかかる時間は短くなっているようですが、まだタイムアウトしています (入力の読み取りが原因ではない可能性があります)。Slava のメソッドはRoad() ctor
(から 2 つ下main
) に実装されています。そのため、80% ではなく 22% の時間がかかります。SortRoadsComparator()
2600万回ということなので最適化を考えています。
コンパレータ コード:
// 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の方法は私にとって最速でした。