Repository navigation
Expand file tree
/
Copy pathfloat_test.cpp
More file actions
152 lines (134 loc) · 3.87 KB
/
Copy pathfloat_test.cpp
File metadata and controls
152 lines (134 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//
// Created by User on 2026/10/3.
//
#include <cstdint>
#include <iostream>
#include <cmath>
#include <stdfloat>
#include <limits>
#include <vector>
#include <climits>
#include "ScopeTimer.hpp"
#include <assert.h>
#include <functional>
void test_func(const std::function<void()> &callback, const char *prompt = "test") {
ScopeTimer timer(prompt);
return callback();
}
template <typename T>
void run_denormal_core() {
const size_t N = 10'000'000;
// 1. 準備常規數與次常規數資料
std::vector<T> normal_data(N, T(1.0001));
T subnormal_val = std::numeric_limits<T>::min() / 2;
std::vector<T> subnormal_data(N, subnormal_val);
// 2. 常規數運算
{
ScopeTimer timer("Normal Loop");
T sum_normal = 0;
for (size_t i = 0; i < N; ++i) {
sum_normal += normal_data[i] * T(0.99);
}
std::cout << sum_normal << '\n';
}
{
ScopeTimer timer("Abnormal Loop");
// 3. 次常規數運算(觸發微碼異常)
T sum_subnormal = 0;
for (size_t i = 0; i < N; ++i) {
sum_subnormal += subnormal_data[i] * T(0.99);
}
std::cout << sum_subnormal << '\n';
}
}
template <typename T>
void run_memory_bound_core(size_t elements) {
ScopeTimer timer("run_memory_bound_core");
std::vector<T> src(elements, T(1.1));
std::vector<T> dst(elements, T(0.0));
// 純粹的記憶體搬移與流水線寫入
for (size_t i = 0; i < elements; ++i) {
dst[i] = src[i] * T(2.0);
}
// 阻斷編譯器優化,確保 dst 陣列的修改不會被跳過
#if defined(__GNUC__) || defined(__clang__)
asm volatile("" : : "g"(dst.data()) : "memory");
#else
volatile T dummy = dst[0];
#endif
}
#define repeat 100'000'000
int main() {
static_assert(sizeof(_Float32) * CHAR_BIT == 32, "Error: _Float32 is not 32-bit on this architecture");
const volatile _Float32 num1 = 1, num2 = 2;
std::cout << std::numeric_limits<_Float32>::digits << '\n';
volatile _Float32 store = num1;
const auto add = [&]() {
store = 0;
for (int i = 0; i < repeat; i++)
store = num1 + num2;
std::printf("%.17g\n", static_cast<double>(store));
};
const auto sub = [&]() {
store = 0;
for (int i = 0; i < repeat; i++)
store = num1 - num2;
std::printf("%.17g\n", static_cast<double>(store));
};
const auto mul = [&]() {
store = 0;
for (int i = 0; i < repeat; i++)
store = num1 * num2;
std::printf("%.17g\n", static_cast<double>(store));
};
const auto div = [&]() {
store = 0;
for (int i = 0; i < repeat; i++)
store = num1 / num2;
std::printf("%.17g\n", static_cast<double>(store));
};
const auto sine = [&]() {
for (int i = 0; i < repeat; i++)
store = std::sin(num1);
std::printf("%.17g\n", static_cast<double>(store));
};
const auto square = [&]() {
for (int i = 0; i < repeat; i++)
store = std::sqrt(num1);
std::printf("%.17g\n", static_cast<double>(store));
};
const auto power = [&]() {
for (int i = 0; i < repeat; i++)
store = std::pow(num1, num2);
std::printf("%.17g\n", static_cast<double>(store));
};
const auto sqrt = [&]() {
for (int i = 0; i < repeat; i++)
store = std::sqrt(num1);
std::printf("%.17g\n", static_cast<double>(store));
};
const auto expon = [&]() {
for (int i = 0; i < repeat; i++)
store = std::exp(num1);
std::printf("%.17g\n", static_cast<double>(store));
};
test_func(add, "add");
test_func(sub, "sub");
test_func(mul, "mul");
test_func(div, "div");
test_func(sine, "sine");
test_func(square, "square");
test_func(power, "power");
test_func(sqrt, "sqrt");
test_func(expon, "expon");
// run_denormal_core<_Float32>();
run_denormal_core<_Float32>();
//
// // L1 Cache 級別(資料量小,完全在極速快取內)
// run_memory_bound_core<_Float32>(4000); // ~16 KB
run_memory_bound_core<_Float32>(2000); // ~16 KB
//
// // RAM 級別(資料量大,榨乾記憶體頻寬,觸發大量 Cache Miss)
// run_memory_bound_core<_Float32>(64'000'000); // ~256 MB
run_memory_bound_core<_Float32>(32'000'000); // ~256 MB
}