-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbefore_optimize.cpp
More file actions
177 lines (153 loc) · 6.66 KB
/
before_optimize.cpp
File metadata and controls
177 lines (153 loc) · 6.66 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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#include <chrono>
#include <cstddef>
#include <iostream>
#include <random>
#include <vector>
using std::vector;
class FigureProcessor {
private:
vector<vector<unsigned char>> figure;
vector<vector<unsigned char>> result;
const size_t size;
public:
FigureProcessor(size_t size, size_t seed = 0) : size(size) {
// !!! Please do not modify the following code !!!
// 如果你需要修改内存的数据结构,请不要修改初始化的顺序和逻辑
// 助教可能会通过指定某个初始化seed 的方式来验证你的代码
// 如果你修改了初始化的顺序,可能会导致你的代码无法通过测试
std::random_device rd;
std::mt19937_64 gen(seed == 0 ? rd() : seed);
std::uniform_int_distribution<unsigned char> distribution(0, 255);
// !!! ----------------------------------------- !!!
// 两个数组的初始化在这里,可以改动,但请注意 gen 的顺序是从上到下从左到右即可。
for (size_t i = 0; i < size; ++i) {
figure.push_back(vector<unsigned char>());
for (size_t j = 0; j < size; ++j) {
figure[i].push_back(static_cast<unsigned char>(distribution(gen)));
}
}
for (size_t i = 0; i < size; ++i) {
result.push_back(vector<unsigned char>());
for (size_t j = 0; j < size; ++j) {
result[i].push_back(0);
}
}
}
~FigureProcessor() = default;
// Gaussian filter
// [[1, 2, 1], [2, 4, 2], [1, 2, 1]] / 16
//FIXME: Feel free to optimize this function
//Hint: You can use SIMD instructions to optimize this function
void gaussianFilter() {
// 处理内部区域
for (size_t i = 1; i < size - 1; ++i) {
for (size_t j = 1; j < size - 1; ++j) {
result[i][j] =
(figure[i - 1][j - 1] + 2 * figure[i - 1][j] +
figure[i - 1][j + 1] + 2 * figure[i][j - 1] + 4 * figure[i][j] +
2 * figure[i][j + 1] + figure[i + 1][j - 1] +
2 * figure[i + 1][j] + figure[i + 1][j + 1]) /
16;
}
}
for (size_t i = 1; i < size - 1; ++i) {
result[i][0] =
(figure[i - 1][0] + 2 * figure[i - 1][0] + figure[i - 1][1] +
2 * figure[i][0] + 4 * figure[i][0] + 2 * figure[i][1] +
figure[i + 1][0] + 2 * figure[i + 1][0] + figure[i + 1][1]) /
16;
result[i][size - 1] =
(figure[i - 1][size - 2] + 2 * figure[i - 1][size - 1] +
figure[i - 1][size - 1] + 2 * figure[i][size - 2] +
4 * figure[i][size - 1] + 2 * figure[i][size - 1] +
figure[i + 1][size - 2] + 2 * figure[i + 1][size - 1] +
figure[i + 1][size - 1]) /
16;
}
for (size_t j = 1; j < size - 1; ++j) {
result[0][j] =
(figure[0][j - 1] + 2 * figure[0][j] + figure[0][j + 1] +
2 * figure[0][j - 1] + 4 * figure[0][j] + 2 * figure[0][j + 1] +
figure[1][j - 1] + 2 * figure[1][j] + figure[1][j + 1]) /
16;
result[size - 1][j] =
(figure[size - 2][j - 1] + 2 * figure[size - 2][j] +
figure[size - 2][j + 1] + 2 * figure[size - 1][j - 1] +
4 * figure[size - 1][j] + 2 * figure[size - 1][j + 1] +
figure[size - 1][j - 1] + 2 * figure[size - 1][j] +
figure[size - 1][j + 1]) /
16;
}
// 处理四个角点
// 左上角
result[0][0] = (4 * figure[0][0] + 2 * figure[0][1] + 2 * figure[1][0] +
figure[1][1]) /
9;
// 右上角
result[0][size - 1] = (4 * figure[0][size - 1] + 2 * figure[0][size - 2] +
2 * figure[1][size - 1] + figure[1][size - 2]) /
9;
// 左下角
result[size - 1][0] = (4 * figure[size - 1][0] + 2 * figure[size - 1][1] +
2 * figure[size - 2][0] + figure[size - 2][1]) /
9;
// 右下角
result[size - 1][size - 1] =
(4 * figure[size - 1][size - 1] + 2 * figure[size - 1][size - 2] +
2 * figure[size - 2][size - 1] + figure[size - 2][size - 2]) /
9;
}
// Power law transformation
// FIXME: Feel free to optimize this function
// Hint: LUT to optimize this function?
void powerLawTransformation() {
constexpr float gamma = 0.5f;
for (size_t i = 0; i < size; ++i) {
for (size_t j = 0; j < size; ++j) {
if(figure[i][j] == 0) {
result[i][j] = 0;
continue;
}
float normalized = (figure[i][j]) / 255.0f;
result[i][j] = static_cast<unsigned char>(
255.0f * std::pow(normalized, gamma) + 0.5f);
}
}
}
// Run benchmark
unsigned int calcChecksum() {
unsigned int sum = 0;
constexpr size_t mod = 1000000007;
for (size_t i = 0; i < size; ++i) {
for (size_t j = 0; j < size; ++j) {
sum += result[i][j];
sum %= mod;
}
}
return sum;
}
void runBenchmark() {
auto start = std::chrono::high_resolution_clock::now();
gaussianFilter();
auto middle = std::chrono::high_resolution_clock::now();
unsigned int sum = calcChecksum();
auto middle2 = std::chrono::high_resolution_clock::now();
powerLawTransformation();
auto end = std::chrono::high_resolution_clock::now();
sum += calcChecksum();
sum %= 1000000007;
std::cout << "Checksum: " << sum << "\n";
auto milliseconds =
std::chrono::duration_cast<std::chrono::milliseconds>(middle - start) +
std::chrono::duration_cast<std::chrono::milliseconds>(end - middle2);
std::cout << "Benchmark time: " << milliseconds.count() << " ms\n";
}
};
// Main function
// !!! Please do not modify the main function !!!
int main(int argc, const char **argv) {
constexpr size_t size = 16384;
FigureProcessor processor(size, argc > 1 ? std::stoul(argv[1]) : 0);
processor.runBenchmark();
return 0;
}