28 Haziran 2018 Perşembe

Atomic İşlemler

Giriş
Atomik işlem bölünemez (indivisible) işlem anlamına gelir. Kod parçalarını lock ile kilitlemekten daha farklı bir kavramdır. Multi-core sistemlerde atomik işlemler için çekirdekler arasında kullanılan bir protokol gerekir.

Atomik işlemler için önce iki kavramı anlamak gerek. Bunlar compiler order ve memory order. 

- İlk kavram derleyicinin kod üretirken, daha optimize olacağını düşündüğü şekilde kodların sırasını değiştirebilmesi. 
- İkinci kavram ise bir çok işlemcinin işleri paralel yürütebilmek için derleyicinin ürettiği kodu, çalışma esnasında farklı sırada çalıştırması. Bunu kontrol etmek için Memory Order kullanılır

Yani işler yazılan koddan çok farklı bir sıralamaya tabi olabiliyor.

Compare Exchange Instruction'lardan Önce
Kullanılan yöntemin açıklaması şöyle
When using a single core, code which disables interrupts and then performs a sequence of memory operations can guarantee that they will be performed atomically. Additionally, many operations like "inc" would be essentially guaranteed to be atomic in the absence of a page fault. Prior to the introduction of a "compare exchange" instruction on the 80486, this was the most practical way to perform many tasks requiring some kinds of atomic operations. Code which relies upon such techniques, however, won't run reliably in a multi-core system unless code running on different cores can be guaranteed not to act in conflicting fashion upon the same region of memory.
Compare Exchange Instructions
Atomik işlemler Compare and SwapTest and Set kümelerine bölünmüştür.

C99
C99 gibi daha eski standartlarda, concurrency  (eş zamanlılık) dahil edilmediği için, atomic değişkenler mevcut değil. Bu yüzden sadece sig_atomic_t gibi interruptability kavramlara yer verilmiş. C2011 standardında ise concurrency dahil ediliyor.

Memory Order Neden Var ?
Çalışma esnasında multi-core işlemciler RAM yavaş kaldığı için kendi önbelleklerine verinin kopyasını alırlar. Örneğin iki çekirdeğin her biri kendi L1 önbelleğinde RAM 'deki aynı veriyi tutuyor olabilir. Önbelleklerin RAM'e yazarken bir şekilde tutarlılığı sağlaması gerekir. Buna cache coherence yani önbellek tutarlılığı denilir. Önbellek tutarlılığı için kullanılan protokollerden bir tanesi MESI'dir.

Coherance Protokolleri Nasıl Çalışır?
Global coherence protokollerinde global state'i dağıtmak için iki yöntem var. İlki directory yöntemi, diğeri ise shared bus yöntemi.


Aslında işlemci ve L1 önbelleği arasında LoadBuffer, StoreBuffer gibi başka kuyruklar da var ancak, basitlik adına bu kadar detaya girmedim. Aşağıdaki şekilde bu yapılar görülebilir.

İşlemciler L2 ve RAM'i de paylaştıkları için daha sonra veriyi eşitlemeye çalışırlar, bu durum da senkronizasyon problemlerine yol açar Aşağıdaki şekilde durum görülebilir.



Memory Order
std::memory_order yazısına taşıdım.

Programlama Dillerinde Atomik Yapılar
Aşağıda bazı programlama dillerinde veya kütüphanelerde bulunan atomik yapılarla ilgili notlarım var.

Atomic Int
boost
atomic yazısına taşıdım

QT
QAtomicInt Sınıfı yazısına taşıdım.

Java
Atomic Java Yapıları yazısına taşıdım.

C#
Interlocked Sınıfı yazısına taşıdım.

Atomic Long
Java
Atomic Java Yapıları yazısına taşıdım.

Atomic Bool
C++
C++'ta atomic bool olarak kullanılabilecek iki sınıf var. Bunlar std::atomic_bool ve std::atomic_flag sınıfları.

1 yorum: