2013-06-06 22 views
18

w Jego Blog Herb Sutter piszeCzy dekompresja atomowa jest droższa niż inkrementacja?

[...] ponieważ zwiększając liczbę odwołań inteligentny wskaźnik można zwykle zoptymalizowany być taka sama jak zwykłego przyrostu w zoptymalizowanym shared_ptr realizacji - po prostu zwykły przyrost instrukcja, i bez ogrodzeń, w wygenerowanym kodzie.

Jednakże zachodzi spadek musi się ubytek atomowej lub jej odpowiednik, który generuje specjalne instrukcje pamięci procesora, które są droższe w siebie, i że w górnej części, które indukują pamięć ograniczeń ogrodzenia na optymalizację otaczającą kodu.

Tekst dotyczy implementacji shared_ptr i nie jestem pewien, czy jego uwaga dotyczy wyłącznie tego czy ogólnie. Z jego sformułowania wynika, że ​​jest to ogólnie.

Ale kiedy o tym myślę, mogę myśleć tylko o "droższym ubytku", gdy natychmiast następuje if(counter==0) - co prawdopodobnie ma miejsce w przypadku shared_ptr.

Dlatego zastanawiam się, czy atomowy operacja ++counter jest (zazwyczaj) zawsze szybciej niż --counter, lub po prostu dlatego, że jest on używanyif(--counter==0)... z shared_ptr?

+1

* "Z jego sformułowania rozumiem, że jest ogólnie" * - Z drugiej strony jednak uważam inaczej. –

+0

Możesz również rzucić okiem na barierę WriteRead, która jest wymagana dla licznika == 0, i która z reguły jest najdroższa, ponieważ jest to jedyna bariera, która wymaga tego zaraz po zapisaniu danych. należy ponownie odczytać, gwarantując synchronizację między rdzeniami. W przypadku licznika ++ wystarczy napisać bez natychmiastowego wymogu uzyskania zsynchronizowanego stanu tej wartości lub innych danych. –

Odpowiedz

11

wierzę, to odnosząc się do faktu, że przyrost może być „ukryty”, gdzie „ubytek i sprawdzić” musi być wykonana jako jedna operacja.

nie jestem świadomy każdej architekturze gdzie --counter (lub counter--, asssuming mówimy o prostych typów danych, takich jak int, char, etc) jest wolniejsze niż ++counter lub counter++.

+0

Co masz na myśli przez "ukryte"? – curiousguy

+0

Jest jednak zupełnie przeciwnie do tego, co mówi. Mówi wprost "zwykły przyrost". Nie chodzi o to, żeby nie sprawdzać wartości później, ani niczego takiego. Chodzi o użycie zwykłego przyrostu (odczytuj cacheline, modyfikuj, zapisuj cacheline), które będzie tracić referencje w obecności współbieżności. Dlatego jestem mocno skłonny powiedzieć, że to, co mówi, jest po prostu złe. Sutter może też powiedzieć złe rzeczy, dlaczego nie. – Damon

16

Omawia to bardziej szczegółowo gdzieś, myślę, że w jego atomic<> weapons prezentacji. Zasadniczo chodzi przede wszystkim o to, gdzie potrzebne są ogrodzenia pamięci w przypadku użycia shared_ptr, a nie jakiejkolwiek wewnętrznej właściwości przyrostów atomowych w stosunku do ubytków.

Powód jest taki, że nie zależy Ci na dokładnym porządkowaniu przyrostów za pomocą zliczanego wskaźnika inteligentnego, o ile nie pominiesz żadnej z nich, ale z ubytkami, ważne jest, abyś miał zainstalowane bariery pamięci, aby na ostatecznym ubytku, który uruchamia usuwanie, nie masz żadnej możliwości wcześniejszego dostępu do pamięci z innego wątku do obiektu, którego właścicielem jest inteligentny wskaźnik po zmianie pamięci po zwolnieniu pamięci.

+0

Ta rozmowa o Herb jest super-duperem! Dzięki! +1 – towi

+0

"Tak długo, jak niczego nie przegapisz" jest jednak ważną częścią. To, i zdarza się przed gwarancją w odniesieniu do ubytku (ale to jest obsługiwane przez ubytek atomowy). Wyraźnie mówi "normalny przyrost", który będzie tracił kilka przyrostów w scenariuszu jednoczesnym. Może on chce powiedzieć coś innego, ale tak właśnie powiedział. – Damon

8

Emisja Sutter mówi o jest fakt, że przyrost liczby odniesienia nie wymaga żadnych dalszych działań dla poprawności. Bierzesz niezerową liczbę referencyjną do innej niezerowej liczby, więc dalsze działania nie są wymagane. Jednak zmniejszenie wymaga podjęcia dalszych działań w celu poprawności. Dekrement przyjmuje niezerową liczbę referencyjną do niezerowej lub zerowej liczby referencyjnej, a jeśli ubytek liczby referencyjnej jest zerowy, musisz wykonać działanie - w szczególności zwolnić odwołany obiekt.Ta dynamika zmniejszania i zmniejszania wymaga większej spójności, zarówno na poziomie ogrodzenia (tak, że dealokacja nie zostanie ponownie uporządkowana z innym odczytem/zapisem w innym rdzeniu, że logika zarządzania pamięcią/buforowaniem procesora została ponownie zamówiona) i na poziom kompilatora (aby kompilator nie porządkował operacji związanych z dekrementacją, co mogłoby spowodować ponowne zamówienie odczytów/zapisów wokół potencjalnej alokacji).

W przypadku opisanego scenariusza Sutter różnica kosztów między przyrostem a dekrementacją nie występuje w samych podstawowych operacjach, lecz w ograniczeniach spójności nałożonych na faktyczne wykorzystanie ubytku (w szczególności na podstawie samego dekrementacji) które nie mają zastosowania do przyrostu.