在数百万次计算中找到最大结果的最有效方法是什么?
What is the most efficient way to find the greatest result of millions of calculations?
基本上,我正在进行数百万次非常简单的计算,并尝试存储最高的结果以在最后打印。我使用的是 C# 控制台应用程序,但这非常简单,以至于与语言无关(这在另一种语言中会表现得更好吗?)
我有:
double output = 0;
//do the calculations
//after each:
if(calculationResult > output) output = calculationResult;
//done with calculations
Console.WriteLine(output);
这可行,但需要很长时间才能完成。我考虑过将答案存储在一个列表中并在计算后对其进行排序,但它在 9GB 左右因 OutOfMemory 而崩溃。
实时比较只存储一个太耗时,但存储所有然后比较会占用太多内存。有什么办法可以优化吗?
编辑:我的解决方案是先将计算次数减半,方法是在到达由答案形成的抛物线的顶点后继续前进。然后我意识到最好的解决方案是将所有内容重构为递归的,从低精度和宽范围开始,然后在提高精度的同时缩小范围。使用 Intel 的 IPP 迁移到 C++ 仅使完成时间减少了约 8%,而操作减少了约 99%。我现在正在研究递归,会回来报告的。
几乎可以肯定,慢的是计算步骤,而不是 if(calculationResult > output) output = calculationResult;
部分。
我不知道你的具体问题是什么,但通常找到数百万计算中最大的最有效方法是仔细考虑你的问题并使用更有效的算法 and/or 数学 因此您不必进行数百万次计算。
正如 Matthew 所说,您需要使流程更有效率。除了找到更好的算法,这里有一些建议:
- 计算是否相互依赖?你可以多线程并将它们分布在多个内核上吗?
- 你能对它们进行矢量化吗,意思是使用 SSE、AVX、AVX2 等?
- 使用一个好的优化编译器,比如 Intel 的。它是周围最好的优化编译器之一。在许多情况下,它会自动为您并行化。
- 重组您的代码以利用缓存层次结构并最大限度地减少未命中。
- 如果你能同时完成 1 和 2,你可以获得显着的速度提升。例如,如果你有一台带超线程和 AVX256 的四核机器,你有 8 个并行的虚拟核心 运行,每个执行 AVX256(4 个双精度值),允许你并行执行 32 个计算。如果您使用服务器 class 机器,每个机器有 2 个插槽和 32 个核心 运行 AVX512。
,您可以想象在理想条件下的加速
- 找到一种允许您利用上述内容的算法。
- 使用 Fortran。我不是在开玩笑。对于数值计算,它无可匹敌。考虑到它如何存储数据,它避免了很多优化问题。
看看Intel's site。由于各种原因,他们希望您能够尽可能多地利用并行性,我不会在这里讨论这些原因。
基本上,我正在进行数百万次非常简单的计算,并尝试存储最高的结果以在最后打印。我使用的是 C# 控制台应用程序,但这非常简单,以至于与语言无关(这在另一种语言中会表现得更好吗?)
我有:
double output = 0;
//do the calculations
//after each:
if(calculationResult > output) output = calculationResult;
//done with calculations
Console.WriteLine(output);
这可行,但需要很长时间才能完成。我考虑过将答案存储在一个列表中并在计算后对其进行排序,但它在 9GB 左右因 OutOfMemory 而崩溃。
实时比较只存储一个太耗时,但存储所有然后比较会占用太多内存。有什么办法可以优化吗?
编辑:我的解决方案是先将计算次数减半,方法是在到达由答案形成的抛物线的顶点后继续前进。然后我意识到最好的解决方案是将所有内容重构为递归的,从低精度和宽范围开始,然后在提高精度的同时缩小范围。使用 Intel 的 IPP 迁移到 C++ 仅使完成时间减少了约 8%,而操作减少了约 99%。我现在正在研究递归,会回来报告的。
几乎可以肯定,慢的是计算步骤,而不是 if(calculationResult > output) output = calculationResult;
部分。
我不知道你的具体问题是什么,但通常找到数百万计算中最大的最有效方法是仔细考虑你的问题并使用更有效的算法 and/or 数学 因此您不必进行数百万次计算。
正如 Matthew 所说,您需要使流程更有效率。除了找到更好的算法,这里有一些建议:
- 计算是否相互依赖?你可以多线程并将它们分布在多个内核上吗?
- 你能对它们进行矢量化吗,意思是使用 SSE、AVX、AVX2 等?
- 使用一个好的优化编译器,比如 Intel 的。它是周围最好的优化编译器之一。在许多情况下,它会自动为您并行化。
- 重组您的代码以利用缓存层次结构并最大限度地减少未命中。
- 如果你能同时完成 1 和 2,你可以获得显着的速度提升。例如,如果你有一台带超线程和 AVX256 的四核机器,你有 8 个并行的虚拟核心 运行,每个执行 AVX256(4 个双精度值),允许你并行执行 32 个计算。如果您使用服务器 class 机器,每个机器有 2 个插槽和 32 个核心 运行 AVX512。 ,您可以想象在理想条件下的加速
- 找到一种允许您利用上述内容的算法。
- 使用 Fortran。我不是在开玩笑。对于数值计算,它无可匹敌。考虑到它如何存储数据,它避免了很多优化问题。
看看Intel's site。由于各种原因,他们希望您能够尽可能多地利用并行性,我不会在这里讨论这些原因。