Önbellek bu kadar hızlı nasıl olabilir?


37

İşte bir önbellek kriterinin ekran görüntüsü:

AIDA64 Önbellek ve Bellek kıyaslama sonuçları

Karşılaştırmada L1 önbellek okuma hızı yaklaşık 186 GB / sn olup gecikme süresi yaklaşık 3-4 saattir. Böyle bir hız nasıl elde edilir?

Buradaki hafızayı göz önünde bulundurun: teorik maksimum hız 6,6 MHz (hafıza frekansı) x 2 (çift veri hızı) x 64 bit (veriyolu genişliği) olup, bu değer yaklaşık 10,6 GB / sn'dir ve 9,6 GB / sn'lik referans değerine yakındır .

Ancak L1 önbellek ile, işlemciyle maksimum frekansında (3 GHz) her döngüde okuyabilsek bile, gerçekçi olmayan sesler elde etmek için yaklaşık 496 veri hattına ihtiyacımız olacaktı. Bu, diğer önbelleklere de uygulanır.

Neyi kaçırıyorum? Bir önbelleğin verimini parametrelerinden nasıl hesaplıyoruz?


14
L1,2,3 önbelleğinin ne kadar küçük olduğunu ve fiziksel olarak bulunduğu yerde eşit olduğunu düşündünüz mü? İpucu, tüm çipin
sahibiyseniz

2
Ayrıca: Benchmark test ettiği bazı verilerin doğrudan bir kayıt içinde tutulmamasını sağlamak için ne yaptığını biliyor mu?
rackandboneman

7
@rackandboneman: AIDA64 saygın bir kriterdir, birinin C'ye girdiği ve derleyicinin bazı yükleri optimize etmesine izin veren bir şey değil! Microbenchmark parçalarının montajda SSE veya AVX versiyonları ile yazılmış olduğunu varsayardım.
Peter Cordes

1
@Peter Kordonlar tatmin edici bir cevap - gerekli bir soruya.
rackandboneman

1
Düşünceleri fiziksel bakış açısına koymak için: 1.4 nanosaniyede ışık bir buçuk metre kadar yürür. Bu, eğer önbellek anakartın diğer tarafında bulunuyorsa, bunun gibi bir gecikme göreliliği bozabilir. Veya bir ölçüm hatası olabilir .
Arthur

Yanıtlar:


35

Bu CPU var ...

2 çekirdek Her çekirdek için bir 32 KB komut ve 32 KB veri birinci seviye önbellek (L1)

İki çekirdek olduğu için, karşılaştırmanın paralel olarak iki iş parçacığı çalıştırmasını bekleyebiliriz. Web siteleri oldukça az bilgi veriyor, ancak buraya bakarsak daha fazla çekirdeğe sahip CPU'ların buna göre daha yüksek L1 verimi sağladığı görülüyor. Bu nedenle, gösterilen tüm çekirdeğin paralel olarak çalıştığı için toplam verim olduğunu düşünüyorum. Bu nedenle, CPU'nuz için, bir çekirdekli ve bir önbellek için ikiye bölmeliyiz:

Read   93 GB/s
Write  47 GB/s
Copy   90 GB/s

Şimdi, "kopya" gerçeği "yazma" den 2 kat daha hızlıdır. Yazabildiğinden daha hızlı nasıl kopyalayabilir? Testin "kopya" olarak gösterdiği şeyin okuma + yazma işleminin toplamı olduğunu ve bu durumda hem 45 GB / sn'de hem okuduğunu hem de yazdığını, ancak 90'ı gösterdiğini iddia edeceğim, çünkü bu bir kıyaslama noktası ve Kim cehennem kriterlerine güveniyor? Öyleyse "kopya" yazsın.

Read   93 GB/s => 30 bytes/clock
Write  47 GB/s => 15 bytes/clock

Şimdi, bir 128 bit kayıt 16 bayttır, yeterince yakındır, bu yüzden bu önbellek iki 128 bit okuma ve saat başına bir yazma yapabilir.

Bu tam olarak bu SSE numara alıştırma talimatlarını gerçekten kolaylaştırmak istersiniz: iki okuma ve bir döngü için bir yazma.

Bu büyük olasılıkla, bir çip içinde çok hızlı bir şekilde çok fazla veri çekmek için olağan yol olan çok sayıda paralel veri hattıyla uygulanacaktır.


4
Dokümanın @ sonraki hack bağlantılarının 55. sayfasında "Dahili olarak, erişim 16 bayta kadardır. [...] İki yükleme işlemi ve bir depolama işlemi her döngüde gerçekleştirilebilir" ifadesini kullanır. Bu, okuma işleminin neden iki kat daha hızlı olduğunu açıklıyor - aynı işlemde iki okuma yapabilir ve aynı zamanda bir yazma da yapabilir.
Tom Carpenter

2
Evet, açıkça BW = okuma ve yazma kopyası sayıyor. Bu, alternatif kadar geçerli görünüyor çünkü okuma ve yazma işlemlerinin paralel olarak gerçekleştirilebilmesi çok önemli. OP’nin L2 / L3 numaralarının, yazma işleminden çok daha yüksek ve bellek için daha düşük olduğuna dikkat edin. DDR3 bellek veri yolu tam çift yönlü değil: okuma ve yazma için aynı veri satırları gerekiyor. (NT mağazaları ve normal mağazalardaki x86 memcpy / memset bant genişliği hakkında daha fazla bilgi için, bkz. Stackoverflow.com/questions/43343231/… ).
Peter Cordes

6
IvyBridge'in aynı saat döngüsünde 2 okuma ve 1 yazma yapabildiğini tahmin ediyorsunuz . Haklısın, ama sadece çok sınırlı şartlar altında. IvB'de yalnızca 2 AGU bağlantı noktası vardır, bu nedenle normalde saat başına 2 bellek op'uyla sınırlıdır, bunlardan biri mağaza olabilir . Ancak 256b AVX yükleri / depoları, yük / mağaza limanlarında 2 döngü alırken, yalnızca ilk döngüde AGU'ya ihtiyaç duyar. Bu nedenle, bir depo adresi uop, herhangi bir yük bant genişliğine mal olmadan 256b yükün 2. döngüsü sırasında 2/3 portunda çalışabilir. (Mağaza verileri Uops 4 numaralı bağlantı noktasında çalışır.) Kaynak: agner.org/optimize microarch pdf
Peter Cordes

2
Bir AMD Bulldozer ailesi veya Ryzen CPU size aynı okuma = 2x yazma sayılarını verir, ancak gerçekte boşlukları olmayan saat başına 2 bellek op'uyla sınırlıdır (en fazla bir yazma olabilir). Oku / yaz / kopyala farkı algılamıyor, ancak Triad can ( a[i] = b[i] + c[i]). BTW, Intel Haswell ve sonraki sürümlerinde, 7 numaralı bağlantı noktasında basit (dizine eklenmemiş) adresleme modlarını kaldırabilecek bir mağaza AGU'su vardır, bu nedenle saat başına 2 yük + 1 mağaza uops'u yürütebilirler. (L1D'ye giden veri yolu 256b'dir, bu nedenle L1D bant genişliğini iki katına çıkarır.) Bkz. David Kanter'in yazdığı yazı: realworldtech.com/haswell-cpu/5
Peter Cordes

1
@AliChen: OP, bant hızından hemen sonra, ne kadar hızlı olabileceğini sormadan önce IvyBridge'in 4 çevrimli yük kullanım gecikmesinden açıkça bahsetti.
Peter Cordes

27

@ peufeu'nun cevabı, bunların sistem genelinde toplam bant genişlikleri olduğuna işaret ediyor. L1 ve L2, Intel Sandybridge ailesindeki her bir çekirdek için özel önbellek, yani sayılar tek bir çekirdeğin yapabileceği miktarın 2 katı. Fakat bu bizi etkileyici bir yüksek bant genişliği ve düşük gecikmeyle bırakıyor.

L1D önbelleği doğrudan CPU çekirdeğine yerleştirilmiştir ve yükleme yürütme birimleri (ve depo tamponu) ile çok sıkı bir şekilde birleştirilmiştir . Benzer şekilde, L1I önbelleği, çekirdeğin komut alma / kod çözme bölümünün hemen yanındadır. (Aslında bir Sandybridge silikon taban planına bakmadım, bu yüzden bu tam anlamıyla doğru olmayabilir. Ön uçtaki sorun / yeniden adlandırma kısmı, muhtemelen güç tasarrufu sağlayan ve daha iyi bant genişliğine sahip olan "L0" kodlu kullanıcı önbelleğine daha yakındır. kod çözücülerden daha fazla.)

Fakat L1 önbellekle her döngüde okuyabilsek bile ...

Neden orada durdun? Sandybridge'den beri Intel ve K8'den beri AMD döngü başına 2 yük yapabilir. Çok portlu önbellek ve TLB'ler bir şeydir.

David Kanter'in Sandybridge mikro mimari yazısının güzel bir şeması var (IvyBridge CPU'nuz için de geçerli):

( "Birleşik zamanlayıcı" ALU tutar ve hafıza onların girişler hazır olması için bekleyen UOPs ve / veya onların yürütme portu bekliyor. (Örn vmovdqa ymm0, [rdi]kod çözümünü beklemek zorunda yük UOP için rdibir önceki eğer add rdi,32henüz infaz edilmemiştir için, Örnek). Intel, zaman çizelgesini yayın / yeniden adlandırma sırasındaki bağlantı noktalarına zamanlıyor.Bu şekil yalnızca bellek aygırları için yürütme bağlantı noktalarını gösteriyor, ancak yürütülemeyen ALU ayraçları da bunun için rekabet ediyor. Emekliliğe kadar ROB'da kalırlar, ancak programlayıcıda yalnızca bir yürütme limanına gönderilinceye kadar kalırlar (Bu, Intel terminolojisidir; diğer insanlar sorunu kullanır ve farklı şekilde gönderir). AMD, tam sayı / FP için ayrı zamanlayıcılar kullanır, ancak adresleme modları her zaman tam sayı kayıtlarını kullanır.

David Kanter'in SnB bellek şeması

Görüldüğü gibi, sadece 2 AGU portu var ( [rdi + rdx*4 + 1024]doğrusal bir adres gibi bir adresleme modu alan ve adres oluşturma birimleri olan adres oluşturma birimleri ). Biri mağaza olmak üzere, saat başına 2 bellek op'unu (her biri 128b / 16 bayt) çalıştırabilir.

Ancak manşetini biraz kandırdı: SnB / IvB 256b AVX yük / depo portunda 2 devir alan tek bir üp olarak yükler / depolar ancak ilk devirde sadece AGU'ya ihtiyaç duyar. Bu, bir mağaza adresinin AGU'da, bu ikinci döngü sırasında hiçbir yük verimini kaybetmeden 2/3 portunda çalışmasını sağlar. Dolayısıyla, AVX ile (Intel Pentium / Celeron CPU'ların desteklemediği: /), SnB / IvB (teoride) döngü başına 2 yük ve 1 mağaza alabilir.

IvyBridge CPU'nuz Sandybridge'in kalıp küçültmesidir ( mov-eleme , ERMSB (memcpy / memset) ve sonraki sayfa donanım ön ayarı). Ondan sonraki nesil (Haswell), veri yollarını yürütme birimlerinden L1'e 128b'den 256b'ye genişleterek saat başına L1D bant genişliğini iki katına çıkardı, böylece AVX 256b yükleri saatte 2 kalabilir. Aynı zamanda basit adresleme modları için ilave bir AGU portu ekledi.

Haswell / Skylake'in en yüksek verimi, saat başına 96 bayt yüklü + depolandı, ancak Intel'in optimizasyon el kitabı, Skylake'in sürekli ortalama veriminin (hala L1D veya TLB'nin özlüyor olmadığını varsayarak) döngü başına ~ 81B olduğunu gösteriyor. (Bir sayısal tam sayı döngü için sürdürmek benim test göre saatin başına 2 yükler + 1 deposu 4 kaynaşık alan UOPs gelen saat başına UOPs) 7 (kaynaşmamış-alan yürütülmesi SKL ile. Ancak bu 64-bit işlenen yerine sahip bir şekilde yavaşlar 32-bit, görünüşe göre bazı mikro mimari kaynak limitleri var ve bu sadece mağaza adreslerini 2/3 portuna düşürmek ve yüklerden döngü çalmaktan ibaret değil.)

Bir önbelleğin verimini parametrelerinden nasıl hesaplıyoruz?

Parametreler pratik çıkış numaraları içermedikçe, yapamazsınız. Yukarıda belirtildiği gibi, Skylake'in L1D'si bile 256b vektörler için yük / mağaza çalıştırma ünitelerine yetişemiyor. Her ne kadar yakın ve 32-bit tamsayılar için de olabilir. (Önbelleğin okuma bağlantı noktalarından daha fazla yük birimine sahip olması anlamlı değildir, ya da tam tersi. Asla tam olarak kullanılamayan bir donanımı dışlarsınız. L1D'nin hatları göndermek / almak için fazladan bağlantı noktaları olabileceğini unutmayın. / diğer çekirdeklerden, hem de çekirdeğin içindeki okuma / yazmalar için.)

Sadece veri yolu genişliklerine ve saatlerine bakmak size tüm hikayeyi vermez. L2 ve L3 (ve bellek) bant genişliği, L1 veya L2'nin izleyebileceği sıra dışı cevapların sayısıyla sınırlandırılabilir . Bant genişliği gecikmeyi geçemez * max_concurrency ve daha yüksek gecikme süresi olan L3 (çok çekirdekli Xeon gibi) yongaları, aynı mikro mimarideki çift / dört çekirdekli CPU'dan çok daha az tek çekirdekli L3 bant genişliğine sahiptir. Bu SO cevabının "gecikmeyle bağlı platformları" bölümüne bakın . Sandybridge ailesi CPU'lar, L1D özlemlerini takip etmek için 10 satır doldurma arabelleğine sahiptir (ayrıca NT mağazaları tarafından da kullanılır).

(Çok sayıda çekirdek etkin olan toplu L3 / bellek bant genişliği büyük bir Xeon'da çok büyük, ancak tek iş parçacıklı kod aynı saat hızında dört çekirdekten daha kötü bant genişliği görüyor, çünkü daha fazla çekirdek ring veriyolunda daha fazla durma anlamına geliyor ve bu nedenle daha yüksek gecikme süresi L3.)


Önbellek gecikme süresi

Böyle bir hız nasıl elde edilir?

L1D önbelleğin 4 çevrim yük kullanım gecikmesi oldukça şaşırtıcı , özellikle de bir adresleme modu ile başlaması gerektiğini göz önünde bulundurarak [rsi + 32], bir sanal adres almadan önce bir ekleme yapmak zorunda . Daha sonra bir eşleşmenin önbellek etiketlerini kontrol etmek için bunu fiziksel olarak çevirmek zorundadır.

( [base + 0-2047]Intel Sandybridge-ailesinde fazladan döngü alma dışındaki adresleme modları , bu nedenle AGU'larda basit adresleme modları için bir kısayol var (düşük yük kullanım gecikmesinin muhtemelen en önemli olduğu, ancak genel olarak yaygın olduğu işaretçi izleme durumları için tipik) (Bkz. Intel'in optimizasyon el kitabı , Sandybridge bölüm 2.3.5.2 L1 DCache.) Bu, bölüm geçersiz kılma ve bunun 0normal olan bölüm temel adresini de varsaymaz .)

Ayrıca, daha önce herhangi bir mağazayla çakışıp çakışmadığını görmek için mağaza tamponunu da araştırmak zorundadır. Ve daha önce (program sırasına göre) mağaza adresi uopu henüz çalışmamış olsa bile bunu çözmesi gerekir, bu nedenle mağaza adresi bilinmiyor. Ancak, bu muhtemelen bir L1D vuruşu kontrolü ile paralel olarak gerçekleşebilir. L1D verilerine ihtiyaç duyulmadığı için, mağaza yönlendirme verileri mağaza tamponundan sağlayabilir, o zaman bu bir kayıp olmaz.

Intel, hemen hemen herkes gibi tıpkı önbellek yeterince küçük ve PIPT önbellek gibi davranması için yeterince yüksek bir ilişkilendirme (sıralamayı yapamaz) VIPT (önbellekleme yapamaz) özelliği gibi standart bir numara kullanarak VIPT (Neredeyse Endekslenmiş Fiziksel Olarak Etiketlenen) önbelleklerini kullanır TLB sanal-> fiziksel aramaya paralel).

Intel'in L1 önbellekleri 32-yönlü, 8-yönlü birleşimdir. Sayfa boyutu 4B'dır. Bu, "dizin" bitlerinin (hangi 8 yol kümesinin belirli bir satırı önbelleğe alabileceğini seçtiği anlamına gelir) tümü sayfa ofsetinin altında olduğu anlamına gelir; yani, bu adres bitleri bir sayfaya mahsustur ve sanal ve fiziksel adreslerde her zaman aynıdır.

Küçük / hızlı önbelleklerin neden yararlı / mümkün olduğunu (ve daha büyük önbelleklerle eşleştirildiğinde iyi çalışır) hakkında daha fazla ayrıntı ve L1D'nin neden L2'den daha küçük / daha hızlı olduğu konusundaki cevabımı görün .

Küçük önbellek, daha büyük önbelleklerde çok pahalı olabilecek şeyleri yapabilir; örneğin, veri dizilerini bir kümeden veri alma gibi alır. Böylece bir karşılaştırıcı hangi etiketin eşleştiğini bulduğunda, SRAM'den zaten alınmış olan sekiz adet 64-baytlık önbellek satırlarından birini karıştırması gerekir.

(Gerçekten o kadar basit değil: Sandybridge / Ivybridge, 16 baytlık sekiz bankanın sekiz bankası olan bir bankalı L1D önbellek kullanıyor. Farklı önbellek hatlarındaki iki aynı bankaya erişim aynı döngüde yürütülmeye çalışırsa önbellek çakışması alabilirsiniz. (8 banka var, bu yüzden adreslerin 128 katı, 2 önbellek satırı gibi adresleri olabilir.)

IvyBridge ayrıca 64B önbellek sınırını geçmediği sürece hizalanmamış erişim için bir ceza almaz. Sanırım düşük adres bitlerine dayanarak hangi bankaların alınacağını belirliyor ve doğru 1 ila 16 bayt veri alabilmek için ne gibi bir kayma olacağına karar veriyor.

Önbellek satırlarında hala sadece tek bir kullanıcı arayüzü var, ancak birden fazla önbellek erişimi var. 4k bölme hariç ceza hala küçük. Skylake, 4k'lık bölmeleri bile oldukça ucuz hale getiriyor ve gecikme süresi yaklaşık 11 döngü, karmaşık bir adresleme moduna sahip normal bir önbellek hattıyla aynı. Ancak 4k'lık bölünmüş verim, bölünmemiş bölünmüşlükten belirgin şekilde daha kötüdür.


Kaynaklar :


1
Bu çok net, ayrıntılı ve ve iyi yazılmış! 1!
sonraki

8

Modern CPU'lar üzerinde ön bellek hemen yanındaki CPU'ya oturur aynı kalıp (chip) üzerine , bu kullanılarak yapılır SRAM çok daha hızlı, fazla DRAM bir PC RAM modülleri için kullanılır.

Bellek birimi başına (bir bit veya bayt) SRAM, DRAM'den çok daha pahalıdır. Bu yüzden DRAM bir PC'de de kullanılıyor.

Ancak SRAM, CPU ile aynı teknolojide yapıldığından, CPU kadar hızlıdır. Ayrıca, 496 satır genişliğinde bir otobüs olması gerekiyorsa, başa çıkacak yalnızca dahili (CPU üzerinde) otobüsler var.


İlginiz için teşekkürler. Kayıt defteri erişim hızlarının 300 GB / sn'nin üzerinde olduğunu belirten birkaç kitapta gördüm, bu durumda 3 GHz'lik bir işlemci için kayıt çıktısı 100 B / devirdir, çünkü bu kayıtlar genellikle 64/128 bit genişliğindedir, o kadar çıktı veremediler. Benimle ilgili olan bu. Verimliliği ifade etmek için GB / sa doğru yoldur.
Knight

3
@Knight, IvB'nin (herhangi bir yüksek performanslı işlemci olarak) 3 ALU op, 2 yük ve 1 mağaza gibi döngü başına birkaç talimat verdiğini unutmayın. Bunların çoğu 2 girdi alabilir (endekslenmiş adresleme için yükler bile) ve yük 3 bile alır. Bu, her biri 8 bayt, 13 bayt, 104 bayt (böylesi epik bir kombinasyona izin verilmemiş olabilir. IvB için durumun devam edemediğine dair bir gösterge değil). Vektör kayıtlarını da dikkate alırsanız, bu sayı daha da artar.
Harold

@harold: related: Haswell ve Skylake, saat başı kayıt okumaları konusunda bir sınırlamaya sahip gibi gözüküyor, ancak bunlar ön uçta olabilir ve bazı girdiler hazırlandıktan sonra bir dizi uygulama yürütmeyi etkilemiyor. Belki başka bir mikro mimari sınırdır, ancak kod başına saatte daha fazla ops sürdürebilmesi gereken darboğazlar buldum. agner.org/optimize/blog/read.php?i=415#852 . Haswell'de en iyi senaryom, saat döngüsü başına ~ 6.5 tamsayı kaydını okudu (devam ediyor). Ayrıca Skylake'de saat başı 7 birim göndermeyi / yürütmeyi de başardım (mağazalar mağaza-adres + mağaza-veridir).
Peter Cordes

@PeterCordes doğru olsa da ön uç olmalı? Tarihsel olarak da sorun olan IIRC (PP2'den Core2'ye) ve kesirli sayıların başka türlü ne anlama geldiğinden emin değilim. Numaralarım yine de biraz kapalı olmasına rağmen
harold

@harold: evet, kesinlikle yeniden adlandırılmış bir tür ön uç darboğaz olduğundan eminim. P6'nın sicil okunan tıkanıklığı, söz konusu kalıcı sicil dosyasından ROB'a okunması gereken "soğuk" kayıtlardaydı. Son zamanlarda değiştirilen kayıtlar hala ROB’daydı ve bunun üzerinde bir darboğaz yoktu. HSW / SKL'de soğuk ve sıcak reglar hakkında fazla araştırma yapmadım, çünkü bir nedenden ötürü döngüyü yineleme başına 4 uops / ideal olarak 1 c'den daha büyük yapmayı düşünmedim. ayy. IDK, yönlendirme ve PRF okumaları arasında ne kadar fark olduğunu gösterir (bu, yürütme sırasında gerçekleşmesi gerekir, yayınlama / yeniden adlandırma değil).
Peter Cordes

4

L1 önbellekleri oldukça geniş bellek yapılarıdır. Intel işlemcilerdeki L1 önbelleklerinin mimarisi bu kılavuzda bulunabilir (bir sonraki bölümde verilen). Ancak, bazı parametrelerin yorumlanması yanlıştır, "önbellek satırı boyutu" "veri genişliği" değildir, bu, atom veri erişiminin seri bloğunun boyutudur.

Tablo 2-17 (bölüm 2.3.5.1), yüklerde (okur), önbellek bant genişliğinin, CYCLE başına çekirdek başına 2x16 = 32 Bayt olduğunu gösterir . Bu tek başına bir 3GHz çekirdekte 96 Gb / s teorik bant genişliği verir. Atıf yapılan referansın neyi rapor ettiği belli değil, paralel olarak çalışan iki çekirdeği ölçüyor gibi görünüyor, bu yüzden iki çekirdekte 192 Gbps yapıyor.


2

Geçit gecikmeleri nedir? 10 pikosaniye mi? Tüm boru hattı operasyonları için çevrim süreleri, çeşitli kod çözme ve veri yolu etkinlikleri ve bir sonraki saat döngüsü başlamadan önce verilerin flip-flop tutulması ile 333 pikosaniyedir.

Bir önbellek okumadaki en yavaş aktivitenin, veri noktalarının yeterince uzağa hareket etmesini bekliyor (muhtemelen bunlar farklı: bir referans ve okuma bitinden bir fiili yük), bir karşılaştırıcı / mandalın pozitif olarak uygulanması için saatli olabilir. ufak bir voltajı büyük bir raya-raya mantık-seviye gerilim salınımına (yaklaşık 1 volt) dönüştürmek için geri bildirim.


1
4 döngü L1D gecikmesinin adres oluşturma (basit adresleme modları için [reg + 0-2047]) ve bir TLB araması ve bir etiket karşılaştırması (8-yollu ilişkilendirme) içerdiğini ve sonuçta 16'ya kadar hizalanmamış baytın yerleştirildiğini unutmayın. Diğer uygulama birimlerine iletmek için yük biriminin çıkış portu. Bu gibi bir işaretçi-kovalayan döngü için 4c gecikme süresi mov rax, [rax].
Peter Cordes
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.