以下 C# 程式計算平方根的 1000 萬次巴比倫迭代。
using System;
using System.Diagnostics;
namespace Performance {
public class Program {
public static void MeasureTime(long n, Action f) {
Stopwatch watch = new Stopwatch();
watch.Start();
for (long i = 0; i < n; i) f();
watch.Stop();
Console.WriteLine($"{(n / watch.ElapsedMilliseconds) / 1000} Mop/s, {watch.ElapsedMilliseconds} ms");
}
public static void TestSpeed(double a) {
Console.WriteLine($"Parameter {a}");
double x = a;
long n = 10_000_000;
MeasureTime(n, () => x = (a / x x) / 2);
Console.WriteLine($"{x}\n");
}
static void Main(string[] args) {
TestSpeed(2);
TestSpeed(Double.PositiveInfinity);
}
}
}
當我在我的計算機上以發布模式運行它時,我得到:
Parameter 2
99 Mop/s, 101 ms
1,41421356237309
Parameter ∞
3 Mop/s, 3214 ms
NaN
這里Mop/s代表每秒百萬次操作。當引數為無窮大時,由于某種原因,代碼速度減慢了 30 倍以上。
為什么是這樣?
為了比較,下面是用 C 20 撰寫的同一個程式:
#include <iostream>
#include <chrono>
#include <format>
namespace Performance {
template <typename F>
void MeasureTime(long long n, F f) {
auto begin = std::chrono::steady_clock::now();
for (long long i = 0; i < n; i) f();
auto end = std::chrono::steady_clock::now();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count();
std::cout << std::format("{0} Mop/s, {1} ms", (n / ms) / 1000, ms) << std::endl;
}
void TestSpeed(double a) {
std::cout << std::format("Parameter {0}", a) << std::endl;
double x = a;
long long n = 10'000'000;
MeasureTime(n, [&]() { x = (a / x x) / 2; });
std::cout << std::format("{0}\n\n", x);
}
}
using namespace Performance;
int main() {
auto inf = std::numeric_limits<double>::infinity();
TestSpeed(2);
TestSpeed(inf);
return 0;
}
當我在發布模式下運行這個程式時,我得到:
Parameter 2
181 Mop/s, 55 ms
1.414213562373095
Parameter inf
192 Mop/s, 52 ms
-nan(ind)
正如預期的那樣;即性能沒有差異。
這兩個程式均在 Visual Studio 2022 版本 17.1.0 中構建。C# 專案是一個 Net Framework 4.7.2 控制臺應用程式。
uj5u.com熱心網友回復:
該問題已通過取消選中Prefer 32-bitsC# 專案選項得到解決。
Enable Enhanced Instruction Set通過將Visual Studio 中的選項更改為No Enhanced Instructions (/arch:IA32)或,我還能夠重現 C 端的性能問題Streaming SIMD Extensions (/arch:SSE)。這些選項僅在構建 32 位程式時可用。正如@shingo 在評論中所暗示的那樣,在較舊的 32 位指令集中使用 NaN 進行計算時似乎存在性能問題。實際上,當引數a設定為無窮大時,給定的代碼僅使用 NaN 進行計算。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/435997.html
上一篇:以串列效率方式搜索(嵌套lis)
