Здравствуйте.
Ниже два примера: в первом создаётся массив объектов со свойствами, во втором создаётся один объект, но на каждое св-во по массиву. Что-то мне подсказывает, что в обоих случаях скорость доступа к данным должна быть одинаковой, но в реальности она отличается и зависит от кол-ва свойств. Подскажите, пожалуйста, есть ли ошибка в медленной версии и, если есть, как сделать правильно.
Пример 1, скорость выполнения 300 мс:
struct Item
{
unsigned int p1;
unsigned int p2;
unsigned int p3;
unsigned int p4;
unsigned int p5;
unsigned int p6;
unsigned int p7;
unsigned int p8;
unsigned int p9;
unsigned int p10;
};
void main()
{
cout << "Start" << endl;
clock_t time;
unsigned int itemsAmount = 100000000;
Item *items = new Item[itemsAmount];
for (unsigned int i = 0; i < itemsAmount; i++)
{
items[i].p1 = 1;
}
time = clock();
unsigned int count = 0;
for (unsigned int i = 0; i < itemsAmount; i++)
{
count += items[i].p1;
}
cout << (clock() - time) << endl;
cout << count << endl;
system("pause");
}
Пример 2, скорость выполнения 30 мс:
struct Item
{
unsigned int *p1;
unsigned int *p2;
unsigned int *p3;
unsigned int *p4;
unsigned int *p5;
unsigned int *p6;
unsigned int *p7;
unsigned int *p8;
unsigned int *p9;
unsigned int *p10;
};
void main()
{
cout << "Start" << endl;
clock_t time;
unsigned int itemsAmount = 100000000;
Item *items = new Item;
items->p1 = new unsigned int[itemsAmount];
items->p2 = new unsigned int[itemsAmount];
items->p3 = new unsigned int[itemsAmount];
items->p4 = new unsigned int[itemsAmount];
items->p5 = new unsigned int[itemsAmount];
items->p6 = new unsigned int[itemsAmount];
items->p7 = new unsigned int[itemsAmount];
items->p8 = new unsigned int[itemsAmount];
items->p9 = new unsigned int[itemsAmount];
items->p10 = new unsigned int[itemsAmount];
for (unsigned int i = 0; i < itemsAmount; i++)
{
items->p1[i] = 1;
}
time = clock();
unsigned int count = 0;
for (unsigned int i = 0; i < itemsAmount; i++)
{
count += items->p1[i];
}
cout << (clock() - time) << endl;
cout << count << endl;
system("pause");
}
Ответ
Это классическая иллюстрация работы кэш-памяти. В первом случае разность адресов двух соседних элементов p1 равна sizeof(Item), во втором случае - sizeof(unsigned int), что в 10 раз меньше. Это означает, что во втором случае при последовательном чтении элементов p1 загрузка в кэш очередного блока памяти будет выполняться реже, что приведет к сокращению времени доступа к данным из этого блока. В вашем случае это дало выигрыш в 10 раз.
Комментариев нет:
Отправить комментарий