如何缩短这个迭代问题的运行时间 我有C++的片段,下面迭代1-50,打印出一个语句,而不是数字,如果元素可以被2或3整除。当前运行时间约为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; } } }

如何缩短这个迭代问题的运行时间 我有C++的片段,下面迭代1-50,打印出一个语句,而不是数字,如果元素可以被2或3整除。当前运行时间约为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; } } },c++,C++,您可以将循环内的endl更改为\n,然后std::cout您可以将循环内的endl更改为\n,然后std::cout我几乎不相信它在任何i7上都那么慢。应该最多运行几毫秒 然而,问题是“如何改进”,为此有几点: 打开优化-O2 删除循环中的std::cout。而是创建一个例如std::string,将输出附加到循环中的该变量,然后在循环之后输出它。仅测量回路,而不是std::cout 使用嵌套循环,如@MichaelDorgan。 我几乎不相信它在任何i7上都会那么慢。应该最多运行几毫秒 然而,

您可以将循环内的endl更改为\n,然后std::cout您可以将循环内的endl更改为\n,然后std::cout我几乎不相信它在任何i7上都那么慢。应该最多运行几毫秒

然而,问题是“如何改进”,为此有几点:

打开优化-O2 删除循环中的std::cout。而是创建一个例如std::string,将输出附加到循环中的该变量,然后在循环之后输出它。仅测量回路,而不是std::cout 使用嵌套循环,如@MichaelDorgan。
我几乎不相信它在任何i7上都会那么慢。应该最多运行几毫秒

然而,问题是“如何改进”,为此有几点:

打开优化-O2 删除循环中的std::cout。而是创建一个例如std::string,将输出附加到循环中的该变量,然后在循环之后输出它。仅测量回路,而不是std::cout 使用嵌套循环,如@MichaelDorgan。
只有50次迭代?将它展开成一个状态机50个状态,1个开关语句,没有数学运算。或者,将其转换为预计算值的单个打印。仍然无法回答为什么程序运行速度如此之慢…

只有50次迭代?将它展开成一个状态机50个状态,1个开关语句,没有数学运算。或者,将其转换为预计算值的单个打印。仍然无法回答为什么程序运行如此之慢…

首先,在您真正需要它之前,不要尝试优化struff,记住这一点。我真的不相信代码需要1.4秒才能运行。但是好的

我能看到的唯一一件事是,您可以做得更好,那就是在编译时进行分组。这样,您就不会计算每个数字的模,您只需查看是否需要打印文本

因此,我所做的是创建一个在编译时求值的函数,如果需要,它返回一个带有文本的const char*,如果不需要,则返回带有nullprt的const char*:

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)
};
最后,在运行时,您只需检查它是否为null:

int main() {
    Timer t{};
    for (int j = 1; j <= max_number; j++) {
        if (results[j]) {
            cout << results[j] << '\n';
        } else {
            cout << j << '\n';
        }
    }
}
结果:

在我的机器中,最初的方法花费了0.05到0.08毫秒。 新方法耗时0.04至0.07毫秒。 所以是的,它更快。但这么快,它将改变一切

现在我真的想弄清楚这一点。在需要之前不要进行优化!。下面是一个例子,它们都是用-O3编译的。差别非常小,代码更大、更复杂。选择简单的方法首先,在你真正需要它之前不要尝试优化struff,记住这一点。我真的不相信代码需要1.4秒才能运行。但是好的

我能看到的唯一一件事是,您可以做得更好,那就是在编译时进行分组。这样,您就不会计算每个数字的模,您只需查看是否需要打印文本

因此,我所做的是创建一个在编译时求值的函数,如果需要,它返回一个带有文本的const char*,如果不需要,则返回带有nullprt的const char*:

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)
};
最后,在运行时,您只需检查它是否为null:

int main() {
    Timer t{};
    for (int j = 1; j <= max_number; j++) {
        if (results[j]) {
            cout << results[j] << '\n';
        } else {
            cout << j << '\n';
        }
    }
}
结果:

在我的机器中,最初的方法花费了0.05到0.08毫秒。 新方法耗时0.04至0.07毫秒。 所以是的,它更快。但这么快,它将改变一切


现在我真的想弄清楚这一点。在需要之前不要进行优化!。下面是一个例子,它们都是用-O3编译的。差别非常小,代码更大、更复杂。喜欢简单的方式

在我的机器上运行相同的代码需要12-66毫秒。我认为问题在于你的时间计量。您可以使用C++的标准工具(如chrono library)测量运行时:


此代码将以毫秒为单位测量实际循环的持续时间,并将其打印出来。它将忽略程序启动、初始化和停止的任何开销,并让您了解实际的代码性能,而不是操作系统的进程运行性能。我打赌它会显示速度的极大提高,对我来说,它会打印总运行时间:4ms。最后。

在我的机器上运行同样的代码需要12-66毫秒。我认为问题在于你的时间计量。您可以使用C++的标准工具(如chrono library)测量运行时:

此代码将以毫秒为单位测量实际循环的持续时间,并将其打印出来。它将忽略程序启动、初始化和停止的任何开销,并让您了解实际的代码性能,而不是操作系统的进程运行性能

曼斯。我打赌它会显示速度的极大提高,对我来说,它会打印总运行时间:4ms。最后。

您确定是指编译时,而不是运行时吗?不管怎样,这两种方法都只需要不到一眨眼的时间。1.4秒的简单计算和50张打印?你的电脑是仓鼠供电的吗?运行一个32gb内存和1080。。。也许我在vs代码上使用的扩展正在抛出错误的运行时,您可以尝试停止使用endl。真的很慢@巴布洛切斯,那是一个货物崇拜的神秘主义者。对于任何体面的现代终端实现或CPU来说,差异可能只有几毫秒甚至纳秒。你确定你指的是编译时,而不是运行时吗?不管怎样,这两种方法都只需要不到一眨眼的时间。1.4秒的简单计算和50张打印?你的电脑是仓鼠供电的吗?运行一个32gb内存和1080。。。也许我在vs代码上使用的扩展正在抛出错误的运行时,您可以尝试停止使用endl。真的很慢@巴布洛切斯,那是一个货物崇拜的神秘主义者。对于任何体面的现代终端实现或CPU来说,差异可能只有几毫秒甚至纳秒。而且,由于I/O几乎总是速度减慢的根源,我相信这一点。但是我仍然不相信它最初运行的时间是1.4秒…@MichaeldOrganger:好吧,如果输出通过管道传输到某种自动测试框架,比如expect工具,那么1.4秒是挂钟时间,而不仅仅是他的程序所花费的时间。我打赌他的报告工具会给他微秒或其他时间。或者他有10个反病毒程序,他的系统是完全拥有的…@Farnsworth:我不希望添加flush来加快速度,它只是恢复您通过删除endl而丢失的行为。我正在使用vs code btwAnd的coderunner扩展,因为I/O几乎总是导致速度减慢的原因,我相信这一点。但是我仍然不相信它最初运行的时间是1.4秒…@MichaeldOrganger:好吧,如果输出通过管道传输到某种自动测试框架,比如expect工具,那么1.4秒是挂钟时间,而不仅仅是他的程序所花费的时间。我打赌他的报告工具会给他微秒或其他时间。或者他有10个反病毒程序,他的系统是完全拥有的…@Farnsworth:我不希望添加flush来加快速度,这只是通过去掉endl来恢复您丢失的行为。我使用的是vs code BTW的coderunner扩展,只测量我认为无法解决原始问题的循环,因为它测量的是不同的I/O时间量。尽管包括I/O,但仍有其他事情在发生。顺便说一句,在-O2,编译器可能会隐藏与不嵌套循环相关的任何内容,这也是因为数学非常简单。我认为仅测量循环会使原始问题失败,因为它测量的是不同的I/O时间量。即使包括I/O,也会发生其他事情。顺便说一句,在-O2,编译器可能会隐藏与不嵌套循环相关的任何内容-再次因为数学很简单。我开始认为这可能与我使用的vs扩展有关…我开始认为这可能与我使用的vs扩展有关…好的,谢谢。问题似乎是我用来编译的VS代码扩展。它输出的运行时不准确。问题是关于优化。这是我唯一想到的事情。祝您的扩展好运,希望您能让它工作得足够有趣-展开循环并预计算值。是的,这是更快的,因为它是值得的:好的,谢谢你。问题似乎是我用来编译的VS代码扩展。它输出的运行时不准确。问题是关于优化。这是我唯一想到的事情。祝您的扩展好运,希望您能让它工作得足够有趣-展开循环并预计算值。是的,它的价值更快: