Çok kelimeli pratik bir karşılaştırma ve değiştirme işlemi


10

Gelen yazıda bu soruya aynıdır başlıkla, yazarlar nasıl oluşturulacağını açıklayan tıkanmasızdır lineerleşebilirdir çok kelimeli CAS sadece tek kelimelik CAS kullanarak işlemi. İlk önce çift karşılaştırma-tek değiştirme işlemini (RDCSS) aşağıdaki gibi tanıtırlar:

word_t RDCSS(RDCSSDescriptor_t *d) {
  do {
    r = CAS1(d->a2, d->o2, d);
    if (IsDescriptor(r)) Complete(r);
  } while (IsDescriptor(r));
  if (r == d->o2) Complete(d); // !!
  return r;
}

void Complete(RDCSSDescriptor_t *d) {
  v = *(d->a1);
  if (v == d->o1) CAS1(d->a2, d, d->n2);
  else CAS1(d->a2, d, d->o2);
}

burada RDCSSDescriptor_taşağıdaki alanlara sahip bir yapıdır:

  • a1 - ilk koşulun adresi
  • o1 - ilk adreste beklenen değer
  • a2 - ikinci koşulun adresi
  • o2 - ikinci adreste beklenen değer
  • n2 - ikinci adrese yazılacak yeni değer

Bu tanımlayıcı, RDCSS işlemini başlatan bir iş parçacığında bir kez oluşturulur ve başlatılır - işlevdeki ilk CAS1 RDCSSbaşarılı olana kadar başka hiçbir iş parçacığının başvurusu yoktur , bu da tanımlayıcıya ulaşılabilir (veya kağıdın terminolojisinde etkin hale gelir ).

Algoritmanın arkasındaki fikir şudur - ikinci bellek konumunu, ne yapmak istediğinizi söyleyen bir tanımlayıcıyla değiştirin. Ardından, tanımlayıcının mevcut olduğu göz önüne alındığında, değerinin değişip değişmediğini görmek için ilk bellek konumunu kontrol edin. Yoksa, ikinci bellek konumundaki tanımlayıcıyı yeni değerle değiştirin. Aksi takdirde, ikinci bellek konumunu eski değerine ayarlayın.

Yazarlar, !!yorumda yer alan çizginin makalede neden gerekli olduğunu açıklamamaktadır . Bana öyle geliyor ki, eşzamanlı bir değişiklik olmaması şartıyla CAS1, Completeişlevdeki talimatlar bu kontrolden sonra her zaman başarısız olacaktır. Ve kontrol ile CAS girişi arasında eşzamanlı bir değişiklik varsa Complete, o zaman kontrolü yapan iş parçacığı CAS içeriğinde hala başarısız olmalıdır Complete, çünkü eşzamanlı değişiklik aynı tanımlayıcıyı kullanmamalıdır d.

Benim soru: işlevinde onay Can RDCSSS, if (r == d->o2)...RDCSS hala bir çift karşılaştırma, tek takas talimat semantiklerine ile atlanabilir lineerleşebilirdir ve kilidi serbest ? ( !!yorum içeren satır )

Değilse, doğruluk sağlamak için bu çizginin gerçekten gerekli olduğu senaryoyu tanımlayabilir misiniz?

Teşekkür ederim.


İlk olarak, neler olup bittiğini anlamak için RDCSSDescriptor_t veri yapısını görmemiz gerekir. İkincisi, teorik bilgisayar bilimi ile ilgilenmediği için bu muhtemelen konu dışıdır; bunu stackoverflow.com'da sormak daha iyi olur.
Dave Clarke

Kağıdın bağlantısı koptu.
Aaron Sterling

1
Bağlantı için özür dilerim - şimdi çalışmalı. Açıklamanın ne olduğunu açıklamak için soruyu güncelledim. Stackoverflow.com'da bunu yayınlamamamın nedeni, SSS'nin bu sitenin bilgisayar bilimindeki araştırma düzeyinde sorular için olduğunu söylemesidir. Bir algoritmanın kilit özgürlüğü ve doğrusallaştırılabilirlik sorularının böyle nitelendirdiğini düşündüm. Umarım SSS'yi yanlış anladım.
axel22

SSS'de kaçırdığınız anahtar kelime "teorik" idi. Bazı insanlar soruyu ilginç buldukça açık bırakacağım.
Dave Clarke

3
@Dave: Bu alt alanda uzman değilim, ama bana göre bu çok tipik bir TCS sorusuna benziyor. İki hesaplama modeli (A: tek kelimeli CAS, B: çok kelimeli CAS ile) ve karmaşıklık ölçüsü (CAS sayısı) verilir ve model B'de B modelini simüle edip edemeyeceğiniz sorulur. ve en kötü durum yükü ile. (Burada simülasyonun sahte kod yerine bir C kodu parçası olarak verilmesi biraz yanıltıcı olabilir; bu bir teori
insanına bunun

Yanıtlar:


9

Eşzamanlı çalışma ortamında basit şeyler tuhaf görünebilir ... umarım bu yardımcı olabilir.

Biz var YERLEŞİK ATOM CAS1 bu anlamsal sahip:

int CAS1(int *addr, int oldval, int newval) {
  int currval = *addr;
  if (currval == oldval) *addr = newval;
  return currval;
}

Biz tanımlamak gerekir ATOMİK RDCSS fonksiyonunu kullanarak CAS1 aşağıdaki anlam sahiptir:

int RDCSS(int *addr1, int oldval1, int *addr2, int oldval2, int newval2) {
  int res = *addr;
  if (res == oldval2 && *addr1 == oldval1) *addr2 = newval2;
  return res;
}

Sezgisel olarak: addr2'deki değeri, yalnızca * addr1 == oldval1 ... başka bir iş parçacığı değiştiriyorsa, diğer iş parçacığının işlemi tamamlamasına yardımcı olabilirsek, CONRURENTENTLY değerini addr2 olarak değiştirmemiz gerekir, sonra yeniden deneyebiliriz.

CASN'yi tanımlamak için RDCSS işlevi kullanılacaktır (makaleye bakın). Şimdi, bir RDCSS Tanımlayıcısını şu şekilde tanımlıyoruz :

RDCSSDESCRI
int *addr1   
int oldval1
int *addr2   
int oldval2
int newval2

Sonra RDCSS'yi aşağıdaki şekilde uygularız:

int RDCSS( RDCSSDESCRI *d ) {
  do {
    res = CAS1(d->addr2, d->oldval2, d);  // STEP1
    if (IsDescriptor(res)) Complete(res); // STEP2
  } while (IsDescriptor(res);             // STEP3
  if (res == d->oldval2) Complete(d);     // STEP4
  return res;
}

void Complete( RDCSSDESCRI *d ) {
  int val = *(d->addr1);
  if (val == d->oldval1) CAS1(d->addr2, d, d->newval2);
    else CAS1(d->addr2, d, d->oldval2);  
}
  • ADIM1: önce * addr2 değerini (kendi) tanımlayıcımız d'ye değiştirmeye çalışıyoruz, eğer CAS1 başarılı olursa res == d-> oldval2 (yani res bir tanımlayıcı DEĞİLDİR)
  • ADIM2: res'in bir tanımlayıcı olup olmadığını kontrol edin, yani STEP1 başarısız oldu (başka bir evre değişti addr2) ... işlemi tamamlayan başka bir evre yardım
  • ADIM3: Tanımlayıcımızı saklamayı başaramazsak ADIM1'i tekrar deneyin
  • ADIM4: beklenen değerimizi addr2'den getirdiysek, tanımlayıcımızı (pointer) addr2'de saklamayı başardık ve newval2'yi * addr2 iif * addr1 == oldval1'e depolama görevimizi tamamlayabiliriz

SORULARINIZA CEVAP

O zaman Step4 atlarsanız if (... && * addr1 == oldval1) * addr2 = newval2 RDCSS semantik parçası (idam ... ya da daha iyisi asla: diğer parçacıkları tarafından bir umpredictable şekilde çalıştırılabilir yardım mevcut).

Yorumunuzda belirttiğiniz gibi, STEP4'teki (res == d1-> oldval2) gerekli değilse: atlansak bile, Complete () içindeki her iki CAS1 de başarısız olur çünkü * (d-> addr2)! = D . Tek amacı bir işlev çağrısından kaçınmaktır.

Örnek T1 = diş1, T2 = diş2:

remember that addr1 / addr2 are in a shared data zone !!!

T1 enter RDCSS function
T2 enter RDCSS function
T2 complete STEP1 (and store the pointer to its descriptor d2 in addr2)
T1 at STEP1 the CAS1 fails and res = d2
T2 or T1 completes *(d2->addr2)=d2->newval2 (suppose that *(d2->addr1)==d2->oldval1)
T1 execute STEP1 and now CAS1 can fail because *addr2 == d2->newval2
   and maybe d2->newval2 != d1->oldval2, in every case at the end 
   res == d2->newval2 (fail) or
   res == d1->oldval2 (success)
T1 at STEP2 skips the call to Complete() (because now res is not a descriptor)
T1 at STEP3 exits the loop (because now res is not a descriptor)
T1 at STEP4 T1 is ready to store d1->newval2 to addr2, but only if
   *(d1->addr2)==d (we are working on our descriptor) and *(d1->addr1)==d1->oldval1
   ( Custom() function)

Teşekkür ederim, iyi bir açıklama. CAS1'in eski değeri döndürdüğü noktayı tamamen kaçırdım, yenisini değil.
axel22

Ancak, senaryoda, son 2 satır şunu söyler: STEP4'teki koşul olmadan, T1 değeri saklayabilir, çünkü addr2içerir d2->newval2. Ama bana öyle geliyor ki, irade içindeki CAS1 Completebaşarısız olacak, çünkü eski değerin tanımlayıcı olmasını bekliyor d1- T1 tarafından hiçbir şey yazılmayacak. Sağ?
axel22

@ axel22: CAS1'i Complete () :-D içinde kaçırdım. Evet haklısın ... örneğim yanlış, if koşulu yalnızca bir işlev çağrısından kaçınmak için kullanılır, if () hiçbir şeyi değiştirmezsek. Açıkça STEP4'teki Tam (d) gereklidir. Şimdi örneği değiştiriyorum.
Marzio De Biasi

Başarısız olmasını beklediğimiz bir CAS'dan kaçınmak, bildiğim kadarıyla bir önbellek optimizasyon tekniğidir, çünkü gerçek donanımda genellikle önbellek hatlarını yıkamak ve bir önbellek hattına özel erişim elde etmek gibi olumsuz etkileri vardır. Sanırım makalenin yazarı algoritmanın doğru olmasının yanı sıra mümkün olduğunca pratik olmasını istedi.
Tim Seguine
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.