연결 리스트에 특정 조건을 만족하는 노드가 있는지 판단할 때, 아래와 같은 구조체를 사용한다.
define SIZE 100000
struct List
{
List* next;
int arr[SIZE];
int value;
};
bool find(struct List* list, int target)
{
while (list)
{
if(list->value == target)
{
return true;
}
list = list->next;
}
return false;
}
struct List
{
List* next;
int value; // <-- HERE!!!
int arr[SIZE];
};
위 구조체에서 arr를 거의 접근하지 않는 데이터라고 가정하자.
노드가 많아지는 경우, 캐시의 공간 제약으로 인해 저장할수 있는 노드의 수가 줄어든다.
따라서 자주 사용되지 않는 데이터를 다른 곳에 저장하고, 이에 대한 포인터만 저장하는 것이 효율적이다.
define SIZE 100000
struct List
{
List* next;
int value;
struct Arr* arr;
};
struct Arr
{
int arr[SIZE];
};
아래와 같은 형태의 2차원 배열을 가정하고, 캐시에는 4개의 블록이 저장될 수 있다고 가정하자.
[
[0, 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]
]
2차원 배열을 순회하며 합산하는 코드를 아래와 같이 작성했다고 하자.
int matrix_summer(int A[M][N])
{
int i, j, sum = 0;
for (i = 0; i < M; i++)
{
for (j = 0; j < N; j++)
{
sum += A[i][j];
}
}
return sum;
}
그런데 만약, 아래와 같이 순회의 순서가 바뀐다면 결과는 매우 달라진다.
int matrix_summer(int A[M][N])
{
int i, j, sum = 0;
for (j = 0; j < N; j++)
{
for (i = 0; i < M; i++)
{
sum += A[i][j];
}
}
return sum;
}