[C++] есть ли смысл в выравнивании на Intel ?
Нагуглилось:
http://lemire.me/blog/archives/2012/05/31/data-alignment-for...
читать включая комментарии, в них едва ли не половина всего интересного.
В связи с этим накладываю еще одно ограничение : пусть моя структура лежит в одной кеш-линии и плохо выровнена. Какие проблемы тем не менее возможны?на новых x86 похоже никаких, но есть ещё странный atom который может чудить.
проблемы:
* дырки в структурах. неэффективное использование памяти и кэшей
* разный layout между i386 и x86_64
если выключить выравнивание
* не все архитектуры позволяют не выравненный доступ, компилятор начнёт городить плохой код или получишь SIGBUS
* производительность всё-же упадёт, хотя бы из-за удвоения cache misses в некоторых случаях
* load/store станут совсем неатомарными
* производительность всё-же упадёт, хотя бы из-за удвоения cache misses в некоторых случаяхв каком случае упадет? можно примерчик описать? напоминаю, что моя структура все же в кеш влезает по условию
Нагуглилось:в общем, я тоже не вижу проблем. хотя автор блога мог бы потестить offset 61, 62, 63, чтобы увидеть проседание скорости из-за расползания инта по двум кеш-линиям

И еще random access неплохо бы потестить, а не последовательный доступ.
Афтар небельмесе в тестировании таких подводных камней.
Если переделать код на рандомное вытаскивание данных из памяти, - апа ! получаем 2х прирост производительности.
в каком случае упадет? можно примерчик описать? напоминаю, что моя структура все же в кеш влезает по условиюЕсли влазит то cache miss будет конечно один.
Мне кажется измерять скорость одной инструкции бесполезно, это какой-то сферический конь.
Если брать какой-то кусок то инструкции явно разобьются на большее число операций и как-то иначе распределятся конвейером.
Если чего-то не хватит или появятся конфликты и параллелизм упадёт то и производительность тоже упадёт.
Нужен некий цикл который на каждом такте нагружает почти все блоки и в нём уже сломать выравнивание.
* load/store станут совсем неатомарнымина самом деле это важное замечание

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <time.h>
#define TEST_ALIGNED 0
#define REPEAT_COUNT 10000
uint16_t indexes[100000];
uint32_t data1[32768];
uint32_t data2[32768];
uint32_t data3[32768];
uint32_t data4[32768];
uint32_t accumulate_non_aligned(uint8_t *data1, uint8_t *data2, uint8_t *data3,
uint8_t *data4, uint16_t *indexes, uint32_t size, int offset) {
int i, j;
uint32_t result = 0;
for (j=0; j<REPEAT_COUNT; j++) {
for (i=0; i<size; i++) {
result += *volatile uint32_t *data1+indexes[i]*4+offset;
result += *volatile uint32_t *data2+indexes[i]*4+offset;
result += *volatile uint32_t *data3+indexes[i]*4+offset;
result += *volatile uint32_t *data4+indexes[i]*4+offset;
}
}
return result;
}
int main(int argc, char **argv) {
int i;
uint32_t result = 0;
clock_t start, end;
srand(1234);
for (i=0;i<100000;i++) {
indexes[i] = rand % 32766;
// indexes[i] = i % 32766;
}
for (i=0;i<32768;i++) {
data1[i] = rand;
data2[i] = rand;
data3[i] = rand;
data4[i] = rand;
}
for (i = 0; i < 8; i++) {
start = clock;
result = accumulate_non_aligneduint8_t *)data1, (uint8_t *)data2,
(uint8_t *)data3, (uint8_t *)data4, indexes, 100000, i);
end = clock;
printf("%d: result = %d, time = %0.5f\n", i, result, doubleend-start)/CLOCKS_PER_SEC;
}
return 0;
}
У меня невыровненный доступ получается медленнее всегда, как при последовательном, так и при произвольном доступе.
На Core 2 E8400 невыровненный на 35% медленнее при произвольном и на 20% при последовательном.
На Core i7 3770K на 10% и 5% соответственно.
Ни твоих 100%, ни авторовских 0% у меня воспроизвести не получилось.
на самом деле это важное замечание т.к. влияет на корректность многопоточного приложенияугу, тут недавно был трэд который вылился в два патча в гцц и один в ядро
В связи с этим накладываю еще одно ограничение : пусть моя структура лежит в одной кеш-линии и плохо выровнена.Как ты собираешься гарантировать первое без избавления от второго? Или так, подрочить кругообразно хочется?
но непонятно нафига всё это — пересортировав поля можно всё выравнять.
пересортировав поля можно всё выравнятьодин задал непонятный вопрос, второй дал непонятный ответ

не представляю как сортировка полей может повлиять на выравнивание

пример структуры, которая влазит в кеш-линию, но которая может быть размещена с нарушением требований выравнивания:
struct A
{
int x;
};
// требование к выравниванию скорее всего "адрес кратен 4"
void * address = // такой адрес, что % cache_line_size == 1;
new (address) A;
A* a = (A*) address; // плохо выровненный объект, помещающийся в кеш-линию
не проще ли его выпрямить чтоб он выравнивал адреса хотя бы на 8 байт вместо
того чтоб упарываться с этим выраванием потом.
В ядре повсюду пару младших бит поинтеров используют под разные интересные нужды
то фражок туда такой воткнут то вообще бит-спинлок. А если где-то вылазит нечётный
поинтер (кроме некторых char *) то это сразу сигнализирует о баге или каррапшне.
у тебя есть специальный кривой аллокатор?есть. собственно вопрос изначальный в том и состоит - надо ли его выпрямлять
не проще ли его выпрямить

чтоб он выравнивал адреса хотя бы на 8 байтпланку надо поднять до 16 : http://liveworkspace.org/code/3ASJEy%242
если не знаешь на каких машинах в будущем этот код будет работать то лучше выправить.
если не знаешь на каких машинахя знаю, это в первом посте указано

я знаю, это в первом посте указанотогда забей
Оставить комментарий
Maurog
а есть ли реальный смысл в выравнивании данных на современных интелах? более конкретно:пусть у меня есть некая структура типа
и я ее "криво" размещаю в памяти (нарушая правило выравнивания)
с какими реальными проблемами я могу столкнуться? это интересно как с точки зрения корректности работы программы, так и с точки зрения перформанса. если такие случаи есть, то хотелось бы их воспроизвести
опытным путем было выяснено, что чтение int работает с одинаковой скоростью независимо от его выравнивания, однако проседание скорости чтения было отмечено при размазывании int по двум кеш-линиям. В связи с этим накладываю еще одно ограничение : пусть моя структура лежит в одной кеш-линии и плохо выровнена. Какие проблемы тем не менее возможны?