Изменить: ST не позволяет размещать более двух ссылок для новичков. Приносим извинения за недостающие ссылки.
Я пытаюсь уменьшить накладные расходы на блокировку в приложении C, где обнаружение изменений глобального состояния имеет значение для производительности. Несмотря на то, что в последнее время я довольно много читал по этой теме (например, много от Х. Саттера и многих других), я не уверен в своей реализации. Я хотел бы использовать комбинацию операции, подобной CAS, и DCL для проверки глобальной переменной Cache-Line Aligned, чтобы избежать ложных -sharing, чтобы обновить локальные данные потока из данных, совместно используемых несколькими потоками. Моя неуверенность в себе в основном связана с
- я не могу интерпретировать документацию GNU по Атрибуты типа
- Кажется, я не могу найти никакой литературы и примеров, которые я мог бы легко перевести на C, таких как aligning-to-cache-line-and-known-the-cache-line-size на ST или 1 (хотя 1 < / em>, кажется, немного отвечает на мой вопрос, я не уверен в своей реализации)
- мой опыт работы с C ограничен
Мои вопросы:
- # P4 #
# P5 # # P6 # # P7 #
# P8 # Предполагается, что 1. верно, что каждый экземпляр
struct cache_line_aligned
(см. Код Пример 1 ниже) выравнивается по64-byte
границам и использует ровно одну строку кэша (при условии, что строки кэша имеют длину64 bytes
)Использование
typedef
для объявления типа не изменяет семантику__attribute__ ((aligned (64)))
(см. Код Пример 2 ниже)Мне не нужно использовать
aligned_malloc
при создании экземпляра структуры, если структура объявлена с__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
}
}
Извините, за длинную статью.
Спасибо!