Изменить: ST не позволяет публиковать более двух ссылок для новичков. Извините за недостающие ссылки.
Я пытаюсь уменьшить накладные расходы на блокировку в приложении C, где обнаружение изменений в глобальном состоянии имеет отношение к производительности. Несмотря на то, что в последнее время я много читаю в этой теме (например, от Х. Саттера и многих других), я не уверен в своей реализации. Я хотел бы использовать комбинацию операции типа CAS и DCL для проверки глобальной переменной Cache-Line Aligned, что позволяет избежать ложного обмена, чтобы обновлять локальные данные потоков из данных, разделяемых несколькими потоками. Недостаточная уверенность в основном связана с
- Мне не удалось интерпретировать документацию GNU на Type-Attributes
- Кажется, я не могу найти какую-либо литературу и примеры, которые я мог бы легко перевести на C, такие как выравнивание-к-кеш-строка-и-знание-кэш-размер строки на ST или 1 (хотя я, кажется, несколько отвечаю на мой вопрос, я не уверен в своей реализации)
- мой опыт работы с C ограничен.
Мои вопросы:
-
Документация Type-Attributes гласит:
Этот атрибут определяет минимальное выравнивание (в байтах) для переменных указанного тип. Например, объявления:
(см. документацию по атрибутам Type-Attributes для декларации)
заставляет компилятор застраховать (насколько это возможно), что каждая переменная, тип которой
struct S
илиmore_aligned_int
будет выделено и выровнено по крайней мере на границе8-byte
. На SPARC, имеющий все переменные типаstruct S
, выровненные с границами8-byte
, позволяет компилятор для использования инструкций ldd и std (doubleword load and store) при копировании одного переменная типа struct S на другую, что повышает эффективность во время выполнения.Означает ли это, что начало
struct S
илиmore_aligned_int
всегда будет выровнено с границей8-byte
? Это не значит, что данные будут заполнены, чтобы использовать ровно 64 байта, правильно? -
Предполагая, что 1. истинно, что каждый экземпляр
struct cache_line_aligned
(см. пример Пример 1 ниже) выравнивается по границам64-byte
и использует ровно одну строку кэша (предполагая, что строки кэша64 bytes
в длину) -
Использование
typedef
для объявления типа не изменяет семантику__attribute__ ((aligned (64)))
(см. пример Пример 2 ниже) -
Мне не нужно использовать
aligned_malloc
при создании экземпляра struct, если struct объявлена с помощью__attribute__ ...
// Example 1
struct cache_line_aligned {
int version;
char padding[60];
} __attribute__ ((aligned (64)));
// Example 2
typedef struct {
int version;
// place '__attribute__ ((aligned (64)))' after 'int version'
// or at the end of the declaration
char padding[60];
} cache_line_aligned2 __attribute__ ((aligned (64)));
И, наконец, эскиз функции, использующей подход с выравниванием по линии с кешем, чтобы эффективно проверить, было ли изменено глобальное состояние каким-либо другим потоком:
void lazy_update_if_changed(int &t_version, char *t_data) {
// Assuming 'g_cache_line_aligned' is an instance of
// 'struct cache_line_aligned' or 'struct cache_line_aligned2'
// and variables prefixed with 't_' being thread local
if(g_cache_line_aligned.version == t_version) {
// do nothing and return
} else {
// enter critical section (acquire lock e.g. with pthread_mutex_lock)
t_version = g_cache_line_aligned.version
// read other data that requires locking where changes are notified
// by modifying 'g_cache_line_aligned.version', e.g. t_data
// leave critical section
}
}
Извините за длинный пост.
Спасибо!