Problem Analysis#
题目已经说了使用向量化指令进行优化,这里使用的是 基于AVX2 SIMD指令集。并使用 Intel intrinsics _mm256_系列函数来实现向量化。具体优化的手段有:
- 交换内外循环: 原代码的外循环是 N 个点,内循环是 M 次迭代。由于内循环每次更新依赖前一次,难以直接向量化内循环。因此,将循环交换为先迭代 M 次,在每次迭代中向量化处理 N 个点。
- 内循环中使用 AVX2 指令:同时处理 8 个点的 x 值,计算 x², x³, 梯度,并进行更新。先处理 8 的倍数部分,然后用标量循环处理剩余点。
完整代码如下,经过测试优化后为满分。
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
| void gradient_descent(float *points, uint32_t N, uint32_t M, float eta, const PolyParams* params) {
// 预先计算常量向量
__m256 a4 = _mm256_set1_ps(4.0f * params->a);
__m256 b3 = _mm256_set1_ps(3.0f * params->b);
__m256 c2 = _mm256_set1_ps(2.0 * params->c);
__m256 d_vec = _mm256_set1_ps(params->d);
__m256 eta_vec = _mm256_set1_ps(eta);
for (uint32_t j = 0; j < M; ++j) { // AVX2 一次处理 8 个 float (256b)
uint32_t i = 0;
for (; i + 8 <= N; i += 8) {
__m256 x = _mm256_loadu_ps(&points[i]);
// compute x^2, x^3
__m256 x2 = _mm256_mul_ps(x, x);
__m256 x3 = _mm256_mul_ps(x2, x);
// compute gradient
__m256 grad = _mm256_mul_ps(a4, x3);
grad = _mm256_add_ps(grad, _mm256_mul_ps(b3, x2));
grad = _mm256_add_ps(grad, _mm256_mul_ps(c2, x));
grad = _mm256_add_ps(grad, d_vec);
// update x -= eta * grad
__m256 delta = _mm256_mul_ps(eta_vec, grad);
x = _mm256_sub_ps(x, delta);
// restore to points
_mm256_storeu_ps(&points[i], x);
}
for (; i < N; ++i) { // 剩余点
float x = points[i];
float grad = poly_gradient(x, params);
x -= eta * grad;
points[i] = x;
}
}
}
|
Using cores: 0,1,2,3
Running case 0/5
cost: 0.0ms
cost: 0.0ms
cost: 0.0ms
cost: 0.0ms
cost: 0.0ms
cost: 0.0ms
Running case 1/5
cost: 30.0ms
cost: 30.0ms
cost: 30.0ms
cost: 30.0ms
cost: 30.0ms
cost: 31.0ms
Running case 2/5
cost: 30.0ms
cost: 31.0ms
cost: 30.0ms
cost: 30.0ms
cost: 30.0ms
cost: 30.0ms
Running case 3/5
cost: 1537.0ms
cost: 1515.0ms
cost: 1568.0ms
cost: 1520.0ms
cost: 1558.0ms
cost: 1529.0ms
Running case 4/5
cost: 517.0ms
cost: 519.0ms
cost: 516.0ms
cost: 521.0ms
cost: 521.0ms
cost: 513.0ms
Case 1 score: 100.00/100 avg_time: 30.2
Case 2 score: 100.00/100 avg_time: 30.2
Case 3 score: 100.00/100 avg_time: 1538.0
Case 4 score: 100.00/100 avg_time: 518.0
Your score: 100.00/100