[英]How to shorten runtime of this iteration problem
我有下面的 C++ 片段,如果元素可以被 2 或 3 整除,它會迭代 1-50 次並打印出一條語句,而不是數字。當前運行時間約為 1.47 秒。 如何優化此問題以加快運行速度?
#include <iostream>
int main() {
for (int j = 1; j <= 50; j++)
{
if (j % 2 == 0 && j % 3 == 0)
{
std::cout << "Both" << std::endl;
}
else if (j % 2 == 0)
{
std::cout << "Two" << std::endl;
}
else if (j % 3 == 0)
{
std::cout << "Three" << std::endl;
}
else
{
std::cout << j << std::endl;
}
}
}
您可以將循環內的endl
更改為"\\n"
,然后std::cout << std::flush;
循環完成后。 這會將沖洗次數減少 50 倍。
由於刷新輸出是這里唯一重要的工作,我希望這可以將您的運行時間減少 98%。 然而,我原以為即使有 50 次刷新,它仍然應該在一秒鍾之內。
首先,不要在真正需要之前嘗試優化 struff (記住這一點)。 我真的不相信該代碼需要 1.4 秒才能運行。 但是沒問題。
我能看到的唯一可以做得更好的是在編譯時將其分組。 這樣你就不會為每個數字計算模數,你只會看看是否需要打印文本。
所以我所做的是創建一個在編譯時評估的函數,如果需要,它返回一個帶有文本的const char*
,如果不需要,則返回 nullprt:
constexpr const char *type(int n) {
if (n % 2 == 0 && n % 3 == 0) {
return "Both";
}
if (n % 2 == 0) {
return "Two";
}
if (n % 3 == 0) {
return "Three";
}
return nullptr;
}
接下來,我有一個包含所有所需結果的數組:
const int max_number = 50;
constexpr const static std::array<const char *, max_number + 1> results{
type(0),
type(1),
type(2),
type(3),
type(4),
type(5),
type(6),
type(7),
type(8),
type(9),
type(10),
type(11),
type(12),
type(13),
type(14),
type(15),
type(16),
type(17),
type(18),
type(19),
type(20),
type(21),
type(22),
type(23),
type(24),
type(25),
type(26),
type(27),
type(28),
type(29),
type(30),
type(31),
type(32),
type(33),
type(34),
type(35),
type(36),
type(37),
type(38),
type(39),
type(40),
type(41),
type(42),
type(43),
type(44),
type(45),
type(46),
type(47),
type(48),
type(49),
type(50)
};
這樣做的結果是,當程序被編譯時,你已經然后分成了gropus。 你可以在這里看到它。 生成的匯編程序將是這樣的:
.L.str:
.asciz "Both"
.L.str.2:
.asciz "Two"
.L.str.3:
.asciz "Three"
results:
.quad .L.str // 0 both
.quad 0 // 1 none
.quad .L.str.2 // 2 Two
.quad .L.str.3 // 3 Three
.quad .L.str.2 // 4 Two
.quad 0 // 5 none
.quad .L.str // etc
.quad 0
// ... and it continues for all values
最后在運行時您只需檢查它是否為空:
int main() {
Timer t{};
for (int j = 1; j <= max_number; j++) {
if (results[j]) {
cout << results[j] << '\n';
} else {
cout << j << '\n';
}
}
}
結果:
所以是的,它更快。 但它會改變任何事情的速度如此之快。
現在我真的很想弄清楚這一點。 在你需要之前不要優化! . 這是一個快速測試,它們都用-O3
編譯。 差異真的很小,代碼更大更復雜。 喜歡簡單的方法
我幾乎不相信它在任何 i7 上都這么慢。 最多應該運行幾毫秒。
然而,問題是“如何改進”,為此有幾點:
-O2
std::cout
。 而是創建一個例如std::string
,將輸出附加到循環中的該變量,並在循環之后輸出它。 只測量循環,而不是std::cout
只有 50 次迭代? 將其展開為狀態機(50 個狀態,1 個 switch 語句,無數學)。 或者,將其轉換為預計算值的單個打印件。 仍然沒有回答為什么程序運行得這么慢......
相同的代碼在我的機器上運行需要 12-66 毫秒。 我認為問題出在你的時間測量上。 您可以使用 C++ 的標准工具(例如chrono
庫)測量運行時間:
#include<iostream>
#include<chrono>
using namespace std;
int main() {
using clock = chrono::high_resolution_clock;
auto start = clock::now();
for (int j = 1; j <= 50; j++) {
if (j % 2 == 0 && j % 3 == 0) {
cout << "Both" << endl;
} else if (j % 2 == 0) {
cout << "Two" << endl;
} else if (j % 3 == 0) {
cout << "Three" << endl;
} else {
cout << j << endl;
}
}
auto end = clock::now();
cout << "Total runtime: " << chrono::duration_cast<chrono::milliseconds>(end - start).count() << "ms." << endl;
}
此代碼將以毫秒為單位測量實際循環的持續時間並打印出來。 它將忽略程序啟動、初始化和停止的任何開銷,並讓您了解實際的代碼性能,而不是操作系統的進程運行設施性能。 我敢打賭,它會顯着提高速度,對我來說,它會打印“總運行時間:4 毫秒”。 到底。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.