Edycja: ST nie zezwala na publikowanie więcej niż dwóch linków dla początkujących. Przepraszamy za brakujące referencje.Sprawdzanie bez blokady dla modyfikacji globalnego stanu współdzielonego w C przy użyciu wyrównania z pamięcią podręczną
Próbuję zmniejszyć obciążenie blokujące w aplikacji C, w której wykrywanie zmian w stanie globalnym ma wpływ na wydajność. Chociaż ostatnio dużo czytałem na ten temat (np. Wiele z H. Suttera i wielu innych), nie jestem pewien co do mojej implementacji. Chciałbym użyć kombinacji operacji podobnej do CAS i DCL dla sprawdzenia zmiennej globalnej z pamięcią podręczną wyrównaną, unikając w ten sposób dzielenia się błędami, aby zaktualizować lokalne dane wątków z danych współdzielonych przez wiele wątków. Mój brak zaufania jest przede wszystkim ze względu na
- mi braku interpretacji dokumentacji GNU na Type-Attributes
- Nie wydaje mogąc znaleźć żadnej literatury i przykładów, które mógłbym łatwo przełożyć do C, takie jak aligning- do-cache-line-a-wiedzy-o-cache-line-format na ST lub 1 (chociaż wydaje się odpowiedzieć na moje pytanie trochę nie jestem przekonana o mojej realizacji)
- moje doświadczenie z C jest ograniczona
Moje pytania:
rodzaju atrybuty państwa dokumentacja:
Ten atrybut określa minimalne wyrównanie (w bajtach) dla zmiennych o określonym typu. Na przykład, deklaracje:
(proszę zapoznać się z dokumentacją typu atrybuty deklaracji)
siła kompilator do ubezpieczenia (o ile to możliwe), że każda zmienna, której typ jest
struct S
lubmore_aligned_int
zostaną przydzielone i wyrównane przynajmniej na granicy8-byte
. Na architekturze SPARC , posiadanie wszystkich zmiennych typustruct S
wyrównanych do granic8-byte
umożliwia kompilatorowi używanie instrukcji ldd i std (ładowanie i przechowywanie podwójnego tekstu) podczas kopiowania jednej zmiennej typu struct S na inną, poprawiając w ten sposób wydajność pracy .Czy to znaczy, że początek
struct S
lubmore_aligned_int
będzie zawsze dostosowane do8-byte
granicy? Nie oznacza to, że dane zostaną dopełnione do użycia dokładnie 64 bajtów, prawda?Przyjmując 1.Jest prawdą, że każdy przypadek
struct cache_line_aligned
(patrz kod Przykład 1 poniżej) wyrównuje na64-byte
granic i wykorzystują dokładnie jeden cache wiersza (zakładając, Cache-linie są64 bytes
długości)Korzystanie
typedef
dla deklaracja typu nie zmieniają semantyki__attribute__ ((aligned (64)))
(patrz kod Przykład 2 poniżej)nie potrzeba używać
aligned_malloc
przy uruchamianiu strukturę, czy struktura jest zadeklarowana__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)));
I wreszcie szkic funkcji, która korzysta z cache-line wyrównane podejście skutecznie sprawdzić, czy stan globalny został zmodyfikowany przez innego wątku:
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
}
}
Przepraszam za długi post.
Dziękujemy!
Pozdrawiam! to bardzo dobrze wyjaśniło sprawy. Nie myślałem o używaniu sizeof do sprawdzenia wyrównania! Zapamiętam to. A co z dynamicznie przydzielanymi wyrównanymi strukturami? Czy 'aligned_malloc' wykona zadanie? – instilled
Prawdopodobnie to zrobi. Przeczytaj jego dokumentację, aby się upewnić. –
Pewnie! Tak zrobię. Jeszcze raz dziękuję za genialną odpowiedź. – instilled