Я запрограммировал достаточно межпроцессных сокетов для кошмаров. Чтобы сделать что-либо поточно-ориентированное в ЦП с оперативной памятью DDR, вы должны выровнять структуру данных в кэш-строке и последовательно упаковать все ваши глобальные переменные в как можно меньшее количество строк кэша.
Проблема с невыровненными межпроцессными данными и слабо упакованными глобальными переменными заключается в том, что это приводит к наложению псевдонимов из-за пропусков кэша. В процессорах, использующих оперативную память DDR, имеется (обычно) набор из 64-байтовых строк кэша. Когда вы загружаете строку кэша, оперативная память DDR автоматически загружает еще несколько строк кэша, но первая строка кэша всегда самая горячая. Что происходит с прерываниями, которые происходят на высоких скоростях, так это то, что страница кэша будет действовать как фильтр нижних частот, как и в аналоговых сигналах, и будет отфильтровывать данные прерываний, ведущие к ПОЛНОСТЬЮ ошибкам, если вы ' не в курсе того, что происходит. То же самое относится и к глобальным переменным, которые не упакованы плотно; если он занимает несколько строк кэша, он будет не синхронизирован, если только вы не сделаете снимок критических межпроцессных переменных и передадите их в стек и регистры, чтобы гарантировать правильную синхронизацию данных.
Раздел .bss (т. Е. Там, где хранятся глобальные переменные, будет инициализирован для всех нулей, но компилятор не будет выравнивать данные для кэширования и выравнивания строк, вам придется сделать это самостоятельно, что также может Хорошее место для использования C ++ Construct in Place . Чтобы узнать математику, стоящую за самым быстрым способом выравнивания указателей, прочитайте эту статью ; я пытаюсь выяснить, придумал ли я этот трюк Вот как будет выглядеть код:
inline char* AlignCacheLine (char* buffer) {
uintptr_t offset = ((~reinterpret_cast<uintptr_t> (buffer)) + 1) & (63);
return buffer + offset;
}
char SomeTypeInit (char* buffer, int param_1, int param_2, int param_3) {
SomeType type = SomeType<AlignCacheLine (buffer)> (1, 2, 3);
return 0xff;
}
const SomeType* create_const_thingy () {
static char interprocess_socket[sizeof (SomeType) + 63],
dead_byte = SomeTypeInit (interprocess_socket, 1, 2, 3);
return reinterpret_cast<SomeType*> (AlignCacheLine (interprocess_socket));
}
По моему опыту, вам придется использовать указатель, а не ссылку.