CPP 056 – Concurency

Concurency Nedir?

Concurency(eşzamanlılık) aynı anda birden fazla görevin yerine getirilmesidir. Maillerinizi okurken, arka planda çalan müzik bunun bir örneğidir. Bilgisayarımızda aynı anda yüzlerce hatta binlerce ufak program/kod parçası aynı anda çalışıyor.

Yeni nesil mimarilerin hepsi(?) çok çekirdekli ama eski tek çekirdekli bilgisayarlarda bile bizler farklı işleri aynı anda yapabiliyorduk. Bu durumda eşzamanlılık kavramı sadece farklı task’ların farklı core’larda çalışma durumundan ibaret bir şey değil. Aynı zamanda farklı task’ların aynı core’da az az ardı ardına çalıştırılarak bize aynı anda çalışıyormuş ilüzyonunu vermektir.

Bilgisayar discrete bir alettir. Gerçek hayat ise (bizim bildiğimiz kadarıyla) continuous bir şeydir. Bizler kendi sınırlı algılarımızla bu dünyaya bakıyoruz. Örneğin bir film şeridini düşünün 24 karenin bir saniyede ardı ardına ekrana yansıtılmasını bizlere continuous olarak algılıyoruz ama bu discrete bir olay. Oynadığımız oyunlarda karakterler bir noktadan diğer noktaya gitmesi de discrete bir olay ama o kadar küçük adımlarla veriliyor ki bizim algımız onu continious bir olay gibi algılıyor. Ta ki fps 20-30 gibi absürt sayılara düşünce. O zaman tık, tık, tık diye ilerleyen karakterimizle mutlu anılar biriktiriyoruz.

İşte concurency de tam olarak böyle bir şey. Core ardı ardına farklı programlardan azıcık azıcık çalıştırıyor ama bunu o kadar hızlı yapıyor ki bizler sanki hepsi aynı anda çalışıyormuş gibi algılıyoruz.

Ne işimize yarayacak?

  • Artık donanımlar fazladan çekirdekle üretiliyor. Fiziksel zorluklar (ve küresel ısınma) sebebiyle çekirdeklerin saat hızlarını (GHz) artıramıyorlar ama işlemcilere fazladan çekirdekler ekleyerek toplam işlem gücünü artırıyorlar. Bu işlem gücünü kullanabilmeye yarar
  • Kullanıcı arayüzüne sahip programlarda büyük işleri yaparken arayüz donmasın diye. Küçük işler için genelde sıkıntı olmaz fakat hesaplama, dosya işlemleri vb şeyleri yaparken mecbur kullanmak gerekiyor.
  • ve buna benzer başka işlerde bizlere sunulmuş bir nimet.

Hello Thread

std::thread ile yeni bir thread oluşturabiliyoruz. Thread oluşturulduğu anda çalışmaya başlar. Thread’e bir tane callable object atmalıyız:

  • fonksiyon
  • lambda
  • functor

gibi.

#include <iostream>
#include <thread>

using namespace std;

void hello() {
	cout << "Hello World!" << endl;
}

int main() {
	thread t(hello); // Create a thread that runs the hello function
	t.join(); // Wait for the thread to finish
}

std::thread ile oluşturduğumuz thread’in işleminin bitmesini beklememiz için join() fonksiyonunu kullanıyoruz.

functor ile:

class Hello{
public:
	void operator()() {
		cout << "Hello World!" << endl;
	}
}; 

int main() {
	Hello h;
	thread t(h); 
	t.join(); 
}

lambda ile :

int main() {
	thread t([]() {cout << "Hello World!" << endl; });
	t.join(); 
}

Argümanla çağırmak için:

void message(string str) {
	cout << str << endl;
}

int main() {
	thread t(message, "Hi!");
	t.join(); 
}

member function ile

class A {
public:
	void message(const string& str) {
		cout << str << endl;
	}
};
int main() {
	A a;
	thread t(&A::message, &a, "Hello World");
	t.join();
}

Cache

bilgisayar temelde iki şeyden oluşur. İşlemci ve hafıza. Hafıza program ve veriyi tutar, işlemci ise programı okuyarak veriyi işler. Gerçek hayatta ise CPU, RAM’deki programı okur ve verileri işler. Fakat burada bir sorunla karşılaşıyoruz. Zaman içinde CPU hızları çok fazla artmasına rağmen RAM’ler bu trendi tutturamadı ve sonuç olarak hafızaya erişim maliyetli/zaman alan bir işe dönüştü. Bu maliyeti azaltmak için işlemcilye yakın daha bellekler eklendi. Bu belleklere/hafızalara cache diyoruz. 3 tür cache vadrı: L1, L2, L3.

İşlemci sırasıyla L1, L2, L3 ve RAM’e bakar. Veriyi cache de bulduysa kullanır (cache hit) bulamadıysa RAM’den getirir (cache miss)

L1, L2, L3 hakkında:

There is a capacity vs latency trade when building caches. It physically takes longer to search and retrieve data from a larger cache. As a result, we get the multi level cache structure found in modern CPUs.

L1 – Extremely fast and extremely low latency, but small capacity.

L2 – Fast and low latency, but medium capacity.

L3 – Medium speed and medium latency, but large capacity.

RAM – Low speed and high latency, but extremely large capacit

To add, there is nothing especially special about the L1 vs L3 in terms of what makes it faster, they are made of the exact same SRAM cells. The reason it’s faster is because L1 is quite literally as inside the CPU core as possible, and smaller is faster too.

L2 is also part of each core, but is less closely connected. L1 data is entirely private and is not shared amongst cores, if they’re working on the same workload there may be redundancy waste if we’re able to trade L3 capacity for L1 on each core.

L3 is one large block that each core is connected to and share this large pool of memory together. L2 data can somewhat be shared between cores with a tagging system, since AMD L3 is a victim cache meaning L3 data is only data that’s been evicted from L1 and L2 and is not copied across all levels. Tags take up some space, but less than the actual data, it also takes more time to request data from another L2 but less than RAM.

L1 is also split in 2 sections, instruction cache and data cache. Instruction cache is located at the front end of the CPU where instructions are decoded. Data cache is located at the end of the execution pipeline.

Synchronization Issues

Farklı threadler aynı anda aynı kaynağa/veriye erişmeye çalıştıklarında problem çıkabilir. 30 kişilik bir sınıf düşünelim her kişinin bir tahta kalemi olsun. Hoca tahtaya 11 sayısını yazdı ve dedi ki:

“Arkadaşlar herbiriniz yoklama sırasına göre tek tek kalkıp bu sayının bir fazlasını tahtaya yazacaksınız.” Bu bildiğimiz klasit dümdüz şekilde akan programlamadır. Bunda bir sıkıntı çıkmadığı sürece her seferinde aynı sonucu alacağımız garantidir. Lakin diğer senaryo için aynısı geçerli değildir:

“Arkadaşlar hepiniz tahtaya kalkıp bu sayıyı bir artırın.” Burada çıkabilecek kaosu tahmin edebilirsiniz. Günün sonunda tahtadaki sayının ne olacağı belli değildir. Aynı durum threadler için de geçerli.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *