面试题答案
一键面试热点代码分析
- 循环赋值部分:
for (int i = 0; i < N; i++) {
arr[i] = i;
}
此循环执行次数为N
(一百万次),每次迭代都要访问数组arr
并赋值,频繁的内存访问操作会成为性能瓶颈。
2. 循环求和部分:
for (int j = 0; j < N; j++) {
sum += arr[j];
}
同样执行N
次,每次都要从内存中读取arr[j]
的值进行累加,大量的内存读取操作也会影响性能。
缓存优化技术改写
- 分块优化:
将数组访问按照缓存行大小进行分块,以减少缓存缺失。假设缓存行大小为
CACHE_LINE_SIZE
(实际应用中需根据硬件确定),可改写如下:
#include <stdio.h>
#define N 1000000
#define CACHE_LINE_SIZE 64
// 假设每个int占4字节,每个缓存行可容纳16个int
#define BLOCK_SIZE (CACHE_LINE_SIZE / sizeof(int))
int main() {
int arr[N];
// 分块赋值
for (int i = 0; i < N; i += BLOCK_SIZE) {
for (int k = 0; k < BLOCK_SIZE && i + k < N; k++) {
arr[i + k] = i + k;
}
}
int sum = 0;
// 分块求和
for (int j = 0; j < N; j += BLOCK_SIZE) {
for (int k = 0; k < BLOCK_SIZE && j + k < N; k++) {
sum += arr[j + k];
}
}
printf("Sum: %d\n", sum);
return 0;
}
- 循环合并: 如果可能,将两个循环合并为一个,减少循环控制开销以及内存访问的不连续性。
#include <stdio.h>
#define N 1000000
int main() {
int arr[N];
int sum = 0;
for (int i = 0; i < N; i++) {
arr[i] = i;
sum += arr[i];
}
printf("Sum: %d\n", sum);
return 0;
}
这种方式减少了对数组arr
的重复遍历,提升了缓存利用率,从而提升性能。但如果在赋值和求和之间有其他逻辑操作,此方法可能不适用。