
ããã¯ããªãŒããŒã¿æ§é ã®æ§ç¯ã¯ãã¢ãããã¯æäœãšã¡ã¢ãªãžã®ã¢ã¯ã»ã¹ãæŽçããæ¹æ³ãšãã2ã€ã®æ±ã«åºã¥ããŠããŸãã ãã®èšäºã§ã¯ãååæ§ãšååããªããã£ãã«çŠç¹ãåœãŠãŸãã
ãç¥ãã ã æããæè¿
ãããããšãïŒ ããã¯ããªãŒã®ããŒãã¯habrasocietyã«ãšã£ãŠè峿·±ããã®ã§ãããç§ã幞ãã«ããŸãã libcdsã®ã³ãŒãã§ããã¹ãã説æããæ¹æ³ã«æ²¿ã£ãŠãåºæ¬ããã¢ã«ãŽãªãºã ã«ã¹ã ãŒãºã«ç§»è¡ããåŠè¡çã«ãµã€ã¯ã«ãæ§ç¯ããããšãèšç»ããŸããã ããããäžéšã®èªè
ã¯ãç¹ã«ãã¯ã«ã¹ãªãã§ãã©ã€ãã©ãªã®äœ¿ç𿹿³ã瀺ãããã«å¹²æžããããšãªã
çŒé¡ãå¿
èŠãšããŸãã ããã«ã¯ç¬èªã®çç±ããããŸãã æçµçã«ãç§ã¯
ããŒã¹ãã®äžèº«ã«ããŸãèå³ããããŸãã-ãããé©çšããæ¹æ³ã説æããŠãã ããïŒ ãããã£ãŠãåäºè©©ãµã€ã¯ã«ã3ã€ã®éšåã«åå²ããŸãã
åºæ¬ ã
å
éš ã
å€éšã§ãã ååäºè©©èšäºã¯ãããŒãã®1ã€ã«é¢é£ããŸãã
åºç€ã§ã¯ãææ°ã®ããã»ããµã®æ§é ã«è³ããŸã§ãäœã¬ãã«ã®ãã®ã«ã€ããŠèª¬æããŸãã ããã¯ç§ã®ãããªäœããã®çç±ã§äžéšã§ãã å
éšçã«ããã¯ããªãŒã®äžçã®è峿·±ãã¢ã«ãŽãªãºã ãšã¢ãããŒããã«ããŒããŸã-ããã¯ãããããã¯ããªãŒã®ããŒã¿æ§é ãå®è£
ããæ¹æ³ã®çè«ã§ãããlibcdsã¯C ++ã³ãŒãã®å°œããããšã®ãªããœãŒã¹ã«ãªããŸãã å€éšããã®libcdã®äœ¿çšã«é¢ããèšäºããããŸã-ãœãããŠã§ã¢ãœãªã¥ãŒã·ã§ã³ããã³ããFAQã
å€åŽããã¯ããªãã®è³ªå/ã³ã¡ã³ã/ææ¡ã芪æãªãè¡å人ãé€ããŸãã
ãããŸã§ã®éãç§ã¯å¿
æ»ã«
å€éšããã®å§ãŸããæºåããŸã-
åºæ¬ã®æåã®éšåã§ãã ãã®èšäºã®å€§éšåã¯ãC ++ã«ã€ããŠã§ã¯ãªãïŒããã«ã€ããŠã§ããããŸãïŒãããã¯ããªãŒïŒã¢ãããã¯ããã¯ããªãŒããªããšã¢ã«ãŽãªãºã ã¯åäœããŸãããïŒã«ã€ããŠã§ããªããçŸä»£ã®ããã»ããµã§ã®ã¢ãããã¯ããªããã£ãã®å®è£
ãšããã®ãããªããªããã£ãã䜿çšãããšãã«çããåºæ¬çãªåé¡ã«ã€ããŠã§ãã
ååæ§ã¯ã
å°çã®æåã®
åã§ããã2ã€ã®æäœã®
åã§ã ã
ã¢ãããã¯æäœã¯ãåçŽãªæäœ-èªã¿åããšæžã蟌ã¿-ããã³ã¢ãããã¯å€æŽæäœïŒèªã¿åã-倿Ž-æžã蟌ã¿ãRMWïŒã«åãããŠããŸãã ã¢ãããã¯æäœã¯ãåå²ã§ããªãæäœãšããŠå®çŸ©ã§ããŸããããã¯ããã§ã«çºçããŠãããããŸã çºçããŠããªããã®ããããã§ãã å®è£
ã®äžé段éã¯èŠããããéšåçãªåœ±é¿ã¯ãããŸããã ãã®æå³ã§ãåçŽãªèªã¿åã/æžãèŸŒã¿æäœã§ãã£ãŠããååãšããŠã¢ãããã¯ã§ã¯ãªãå ŽåããããŸãã ããšãã°ãã¢ã©ã€ã¡ã³ããããŠããªãããŒã¿ã®èªã¿åãã¯éã¢ãããã¯ã§ããx86ã¢ãŒããã¯ãã£ã§ã¯ããã®ãããªèªã¿åãã«ããå
éšäŸå€ãçºçããããã»ããµãä»ã®ã¢ãŒããã¯ãã£ïŒSparcãIntel ItaniumïŒã§ããŒã¿ãéšåçã«èªã¿åãããã«åŒ·å¶ãããŸã-èŽåœçãªãšã©ãŒïŒã»ã°ã¡ã³ããŒã·ã§ã³ãã©ãŒã«ãïŒåŠçãããŸãããããã§ã¯ååæ§ã«ã€ããŠã®è©±ã¯ã§ããŸããã ææ°ã®ããã»ããµã¯ãæŽæ°åãšãã€ã³ã¿åã®æŽæ°åã®ã¿ãèªã¿æžãããååæ§ãä¿èšŒããŸãã ææ°ã®ã³ã³ãã€ã©ã¯ãåºæ¬åã®å€æ°ã®æ£ããã¢ã©ã€ã¡ã³ããä¿èšŒããŸãããã¢ã©ã€ã¡ã³ããããŠããªãåŒã³åºãã®äŸãå
šäœã«èšè¿°ããããšã¯é£ãããããŸããã æ§é ïŒãµã€ãº4ã8ãã€ãã«åãŸãïŒãã¢ãããã¯ã«åŠçããå Žåã¯ãã³ã³ãã€ã©ãŒãã£ã¬ã¯ãã£ãïŒå±æ§ïŒã䜿çšããŠé©åãªã¢ã©ã€ã¡ã³ããèªåã§è¡ãå¿
èŠããããŸãïŒåã³ã³ãã€ã©ãŒã¯ãããŒã¿/åã¢ã©ã€ã¡ã³ããæå®ããç¬èªã®ç¬èªã®æ¹æ³ããµããŒãããŠããŸãïŒã ãšããã§ã
libcdsã©ã€ãã©ãªã«ã¯ãã¢ã©ã€ã¡ã³ããããããŒã¿ã宣èšãããšãã«ã³ã³ãã€ã©ã«äŸåããéšåãé ãäžé£ã®è£å©åãšãã¯ããå«ãŸããŠããŸãã
æ¯èŒãšäº€æ
èªã¿åã/æžã蟌ã¿ã®ã¿ã䜿çšããããã¯ããªãŒã³ã³ãããŒã¢ã«ãŽãªãºã ãèãåºãããšã¯ãå¯èœãªå Žåã¯éåžžã«å°é£ã§ãïŒä»»æã®æ°ã®ã¹ã¬ããã«å¯Ÿãããã®ãããªããŒã¿æ§é ã¯ããããŸããïŒã ãã®ãããããã»ããµã¢ãŒããã¯ãã£ã®éçºè
ã¯ãã¢ã©ã€ã³ãããã¡ã¢ãªã»ã«ãã¢ãããã¯ã«èªã¿æžãã§ããRMWæäœãå®è£
ããŠããŸãïŒæ¯èŒãšã¹ã¯ããïŒCASïŒããã§ãããšè¿œå ïŒFAAïŒããã¹ããšã»ããïŒTASïŒãªã©ãã¢ã«ãããã¯ç°å¢ã§ã¯ãæ¯èŒãšã¹ã¯ããïŒCASïŒæäœã¯åºæ¬ãšèŠãªãããŸãã åœŒå¥³ã®æ¬äŒŒã³ãŒãã¯ç°¡åã§ãïŒ
bool CAS( int * pAddr, int nExpected, int nNew ) atomically { if ( *pAddr == nExpected ) { *pAddr = nNew ; return true ; } else return false ; }
ã€ãŸãã
pAddr
ã®å€æ°ã®çŸåšã®å€ãæåŸ
ããã
pAddr
ãšçããå Žåã倿°ã
nNew
èšå®ããŠ
true
ãè¿ããããã§ãªãå Žåã¯
false
è¿ã
false
ã倿°ã®å€ã¯å€æŽãããŸããã ããã¯ãã¹ãŠã¢ãããã¯ã«å®è¡ãããŸããã€ãŸããåå²äžå¯èœã§ãç®ã«èŠããéšåçãªå¹æã¯ãããŸããã CASã䜿çšãããšãä»ã®ãã¹ãŠã®RMWæäœã衚çŸã§ããŸããããšãã°ããã§ããã¢ã³ãã¢ãã¯æ¬¡ã®ããã«ãªããŸãã
int FAA( int * pAddr, int nIncr ) { int ncur ; do { ncur = *pAddr ; } while ( !CAS( pAddr, ncur, ncur + nIncr ) ; return ncur ; }
CASã®ãã¢ã«ãããã¯ãããŒãžã§ã³ã¯ãå®éã«ã¯åžžã«äŸ¿å©ã§ãããšã¯éããŸãããCASã«é害ãçºçããå Žåãã»ã«å
ã®çŸåšã®å€ã«é¢å¿ãããããšãå€ãããã§ãã ãããã£ãŠããã®ãããªCASã®ããªã¢ã³ãã¯ãå€ãã®å Žåèæ
®ãããŸãïŒãããã
å€ã®CASãã¢ãããã¯ã«å®è¡ãããŸãïŒã
int CAS( int * pAddr, int nExpected, int nNew ) atomically { if ( *pAddr == nExpected ) { *pAddr = nNew ; return nExpected ; } else return *pAddr }
C ++ 11ã§ã¯ã
compare_exchange
颿°ïŒå³å¯ã«èšãã°ãC ++ 11ã«ã¯ãã®ãããªé¢æ°ã¯ãããŸããããã®çš®é¡ã¯
compare_exchange_strong
ãš
compare_exchange_weak
ã§ãããåŸã§èª¬æããŸãïŒã¯ããããã®ãªãã·ã§ã³ã®äž¡æ¹ãã«ããŒããŸãã
bool compare_exchange( int volatile * pAddr, int& nExpected, int nNew );
nExpected
åŒæ°
nExpected
åç
§ã«ãã£ãŠæž¡ãããå
¥åã«ã¯
pAddr
ã®å€æ°ã®æåŸ
å€ãå«ãŸããåºåã«ã¯å€æŽåã®å€ãå«ãŸããŸãã 颿°ã¯æåã®ãµã€ã³ãè¿ããŸãïŒã¢ãã¬ã¹ã«å€
nExpected
ãå«ãŸããŠããå Žåã¯
nExpected
ïŒãã®å Žåã¯
nNew
ã«å€æŽãã
nNew
ïŒã倱æããå Žåã¯
false
ã§ãïŒ
nExpected
ã«ã¯ã¢ãã¬ã¹
pAddr
倿°ã®çŸåšã®å€ãå«ãŸããŸãïŒã CASæäœã®ãã®ãããªæ®éçãªæ§é ã¯ãCASã®ãã¢ã«ãããã¯ãå®çŸ©ã®äž¡æ¹ã®ããŒãžã§ã³ãã«ããŒããŸãããå®éã«ã¯ã
nExpected
åŒæ°
nExpected
åç
§ã«ãã£ãŠæž¡ããã倿Žã§ããããšãèŠããŠããå¿
èŠãããããã
compare_exchange
ãšã©ãŒ
compare_exchange
䌎ããŸãã
compare_exchange
ã
compare_exchange
ãã§ããã¢ã³ãã¢ãããªããã£ãã¯æ¬¡ã®ããã«èšè¿°ã§ããŸãã
int FAA( int * pAddr, int nIncr ) { int ncur = *pAddr; do {} while ( !compare_exchange( pAddr, ncur, ncur + nIncr ) ; return ncur ; }
ABAã®åé¡
CASããªããã£ãã¯ãã¹ãŠã®äººã«é©ããŠããŸãããé©çšããããšã
ABAåé¡ãšåŒã°ããæ·±å»ãªåé¡ãçºçããå¯èœ
æ§ããããŸãã ããã説æããã«ã¯ãCASæäœã䜿çšããå
žåçãªãã¿ãŒã³ãèæ
®ããå¿
èŠããããŸãã
int nCur = *pAddr ; while (true) { int nNew = if ( compare_exchange( pAddr, nCur, nNew )) break; }
å®éãCASãæ©èœãããŸã§ã«ãŒãã§ããã³ã°ãããŸãã ã«ãŒããå¿
èŠã§ãããªããªãã
pAddr
ã§å€æ°ã®çŸåšã®å€ãèªã¿åã£ãŠããæ°ããå€
nNew
ãèšç®ãã
nNew
倿°ã¯å¥ã®ã¹ã¬ããã«ãã£ãŠå€æŽã§ããããã§ãã

ABAã®åé¡ã¯æ¬¡ã®ããã«èª¬æãããŸããã¹ã¬ããXããããŒã¿ãžã®ãã€ã³ã¿ãŒãå«ãå
±æã»ã«ããAã®å€ãèªã¿åããšããŸãã æ¬¡ã«ãå¥ã®ã¹ã¬ããYããã®ã»ã«ã®å€ãBã«å€æŽããåã³Aã«å€æŽããŸããããã€ã³ã¿ãŒAã¯ä»ã®ããŒã¿ãæããŸãã ã¹ã¬ããXãCASããªããã£ãã䜿çšããŠã»ã«å€ã倿Žããããšãããšããã€ã³ã¿ãŒãAã®ä»¥åã®ïŒèªã¿åãïŒå€ãšæ¯èŒããŠæåããCASã®çµæã¯æåããŸãããAã¯å®å
šã«ç°ãªãããŒã¿ãæããŸãïŒ ãã®çµæããããŒã¯ãªããžã§ã¯ãã®å
éšæ¥ç¶ãæ··ä¹±ãããå¯èœæ§ããããŸãïŒãã®çµæã厩å£ããå¯èœæ§ããããŸãïŒã
ABAã®åé¡ãçºçããããããã¯ããªãŒã¹ã¿ãã¯ã®å®è£
ãæ¬¡ã«ç€ºããŸã[Mic04]ïŒ
// Shared variables static NodeType * Top = NULL; // Initially null Push(NodeType * node) { do { NodeType * t = Top; node->Next = t; } while ( !CAS(&Top,t,node) ); } NodeType * Pop() { Node * next ; do { NodeType * t = Top; if ( t == null ) return null; next = t->Next; } while ( !CAS(&Top,t,next) ); return t; }
次ã®äžé£ã®ã¢ã¯ã·ã§ã³ã¯ãã¹ã¿ãã¯æ§é ã®éåã«ã€ãªãããŸãïŒABAã®åé¡ã瀺ãã®ã¯ãã®ã·ãŒã±ã³ã¹ã ãã§ã¯ãªãããšã«æ³šæããŠãã ããïŒã
ã¹ã¬ããx | ã¹ã¬ããy |
Pop() åŒã³åºããŸãã å®äºã©ã€ã³Pop4 ã 倿°å€ïŒ t == A
next == A->next
| |
|
NodeType * pTop = Pop()
pTop ==ã¹ã¿ãã¯ã®æäžéšãã€ãŸãA
Pop()
Push( pTop ) ã¹ã¿ãã¯ã®äžçªäžã¯åã³Aã§ã
A->next ã倿ŽãããŠããããšã«æ³šæããŠãã ãã
|
ã©ã€ã³ã¯Pop5 ã CASã¯æåããŸãããã Top->next ãã£ãŒã«ã å€ãå²ãåœãŠã ã¹ã¿ãã¯äžã«ååšããªã ã¹ã¬ããYãããã·ã¥ããããã ã¹ã¿ãã¯Aããã³A->next ãã ãããŠããŒã«ã«å€æ°next å€ãå€ãä¿åããŸãA->next
| |
ABAã®åé¡ã¯ãCASããªããã£ãã«åºã¥ããã¹ãŠã®ããã¯ããªãŒã³ã³ãããŒã®æšäºã§ãã ããã¯ãã³ã³ããããèŠçŽ Aãåé€ããå¥ã®ïŒBïŒã«çœ®ãæãããã®åŸåã³AïŒãããã£ãŠã
ABAåé¡ããšããååïŒã«çœ®ãæããããããã«ãã¹ã¬ããã³ãŒãã§ã®ã¿çºçããŸãããå¥ã®ã¹ã¬ããã¯åé€ããèŠçŽ ãžã®ãã€ã³ã¿ãä¿æããŸãã ã¹ã¬ãããç©ççã«Aãåé€ãïŒ
delete A
ïŒã次ã«
new
ãåŒã³åºããŠæ°ããèŠçŽ ãäœæããå Žåã§ããã¢ãã±ãŒã¿ãŒãã¢ãã¬ã¹Aãè¿ããªããšããä¿èšŒã¯ãããŸããïŒé©åãªã¢ãã±ãŒã¿ãŒã¯ãããè¡ãã ãã§ãïŒã å€ãã®å ŽåãäžèšãããæŽç·Žãããæ¹æ³ã§çŸãã2ã€ã§ã¯ãªããããå€ãã®ãããŒã«åœ±é¿ããŸãïŒãã®æå³ã§ãååãªæ³ååãããéããABCBAåé¡ãABABAåé¡ãªã©ã«ã€ããŠè©±ãããšãã§ããŸãïŒããããŠãã®èå¥ã¯åžžã«éèŠãªã¿ã¹ã¯ã§ãã ABAã®åé¡ã«å¯ŸåŠããæ¹æ³ã¯ã
é
å»¶å²ãåœãŠè§£é€ ããŸãã¯åé€ãããèŠçŽ ãžã®ããŒã«ã«ãŸãã¯ã°ããŒãã«åç
§ã誰ãïŒç«¶åããã¹ã¬ãããïŒããªãããšãå®å
šã«ä¿èšŒããæç¹
ã§ã®èŠçŽ ã®
å®å
šãªã¡ã¢ãªåçã§ã ã
ãããã£ãŠãããã¯ããªãŒæ§é ããèŠçŽ ãåé€ããããšã¯2段éã§ãã
- æåã®ãã§ãŒãºã¯ãããã¯ããªãŒã³ã³ããããã®èŠçŽ ã®é€å€ã§ãã
- 2çªç®ã®ãã§ãŒãºïŒæ®ã眮ãïŒã¯ãèŠçŽ ãžã®åç
§ããªãå Žåã®èŠçŽ ã®ç©ççãªåé€ã§ãã
次ã®ããããã®èšäºã§ãããŸããŸãªé
å»¶åé€ã¹ããŒã ã«ã€ããŠèª¬æããŸãã
ããŒããªã³ã¯/ã¹ãã¢æ¡ä»¶ä»ã
ãããããCASã®äœ¿çšæã«ABAã®åé¡ãååšãããããããã»ããµèšèšè
ã¯ABAã®åé¡ã®åœ±é¿ãåããªãä»ã®RMWæäœãæ¢ãããã«ãªããŸããã ãããŠããã®ãããªæäœãèŠã€ãããŸãã-
ããŒããªã³ã¯/ã¹ãã¢æ¡ä»¶ä»ãã®ãã¢ïŒLL / SCïŒã ãããã®æäœã¯éåžžã«ç°¡åã§ã-æ¬äŒŒã³ãŒãã¯æ¬¡ã®ãšããã§ãã
word LL( word * pAddr ) { return *pAddr ; } bool SC( word * pAddr, word New ) { if ( pAddr LL) { *pAddr = New ; return true ; } else return false ; }
LL / SCãã¢ã¯ãæŒç®åãã©ã±ãããšããŠæ©èœããŸãã
ããŒããªã³ã¯ ïŒLLïŒæäœã¯ãåã«å€æ°ã®çŸåšå€ã
pAddr
ãŸãã
ã¹ãã¢æ¡ä»¶ä»ã ïŒSCïŒæäœã¯ã
pAddr
ã®ããŒã¿ãèªã¿åã
ããŠãã
倿Žãã pAddr
ããªãå Žåã«ã®ã¿ã以åã«èªã¿åãããLLæäœã¢ãã¬ã¹
pAddr
ä¿åãããŸãã ãã®å Žåã倿Žãšã¯ã
pAddr
ã¢ãã¬ã¹ã
pAddr
ãã£ãã·ã¥ã©ã€ã³ã®å€æŽãæããŸãã LL / SCãã¢ãå®è£
ããã«ã¯ãããã»ããµéçºè
ã¯ãã£ãã·ã¥æ§é ã倿Žããå¿
èŠããããŸããããããããåãã£ãã·ã¥ã©ã€ã³ã«ã¯è¿œå ã®ã¹ããŒã¿ã¹ããããå¿
èŠã§ãã LLæäœã«ãã£ãŠèªã¿åããããšããã®ããããèšå®ïŒãªã³ã¯ïŒããããã£ãã·ã¥ã©ã€ã³ãžã®æžã蟌ã¿ïŒãŸãã¯ãã£ãã·ã¥ããã®ããã·ã¥ïŒã«ããããããã¯ãªã¢ãããä¿ååã®SCæäœã«ããããã®ãããããã£ãã·ã¥ã©ã€ã³ã«èšå®ãããŠãããã©ããã確èªãããŸãïŒããã= 1ã®å Žåããã£ãã·ã¥ã©ã€ã³ã倿Žãã人ã¯ããŸãã
pAddr
ã®å€ã¯æ°ãããã®ã«å€æŽãããSCæäœã¯æåããŸãããã以å€ã®å Žåãæäœã¯å€±æãã
pAddr
ã®å€ã¯å€æŽãããŸããã
CASããªããã£ãã¯ã次ã®ããã«LL / SCãã¢ã䜿çšããŠå®è£
ã§ããŸãã
bool CAS( word * pAddr, word nExpected, word nNew ) { if ( LL( pAddr ) == nExpected ) return SC( pAddr, nNew ) ; return false ; }
ãã®ã³ãŒãã®ãã«ãã¹ãããã®æ§è³ªã«ãããããããããã¯ã¢ãããã¯CASãå®è¡ããããšã«æ³šæããŠãã ãããã¿ãŒã²ããã¡ã¢ãªã»ã«ã®å
容ã¯å€åããªããã
ã¢ãããã¯ã«å€åããŸãã CASããªããã£ãã®ã¿ããµããŒãããã¢ãŒããã¯ãã£ã§LL / SCãã¢ãå®è£
ããããšã¯å¯èœã§ãããããã»ã©ããªããã£ãã§ã¯ãããŸããã ããã§ã¯æ€èšããŸãã;èå³ã®ããæ¹ã¯èšäº[Mic04]ãåç
§ããŠãã ããã
ææ°ã®ããã»ããµã¢ãŒããã¯ãã£ã¯ã2ã€ã®å€§ããªãã£ã³ãã«åãããŠããŸã-ã³ãã³ãã·ã¹ãã ã§CASããªããã£ãããµããŒããããã®ãšãLL / SCã®ãã¢ããµããŒããããã®ããããŸãã CASã¯ãx86ãIntel ItaniumãSparcã¢ãŒããã¯ãã£ã«å®è£
ãããŠããŸãã ããªããã£ãã¯IBM System 370ã¢ãŒããã¯ãã£ãŒã§åããŠç»å ŽããLL / SCãã¢ã¯PowerPCãMIPSãAlphaãARMã¢ãŒããã¯ãã£ãŒã§ãã DECã«ãã£ãŠæåã«ææ¡ãããŸããã LL / SCããªããã£ããæãçæ³çãªæ¹æ³ã§ææ°ã®ã¢ãŒããã¯ãã£ã«å®è£
ãããŠããªãããšã«æ³šæãã䟡å€ããããŸãïŒããšãã°ãç°ãªãã¢ãã¬ã¹ã§ãã¹ããããLL / SCåŒã³åºããè¡ãããšã¯ã§ããŸããããªã³ã¯ãã©ã°ã®èª€ã£ããªã»ãããå¯èœã§ãïŒããããåœå
±æã以äžãåç
§ïŒããã©ã°æ€èšŒããªããã£ãã¯ãããŸããLL / SCãã¢å
ã§ãªã³ã¯ãããŠããŸãã
C ++ã®èгç¹ãããC ++ 11æšæºã¯LL / SCãã¢ãèæ
®ãããã¢ãããã¯ããªããã£ã
compare_exchange
ïŒCASïŒãšããããæŽŸçããã¢ãããã¯ããªããã£ã
fetch_add
ã
fetch_sub
ã
exchange
ãªã©ã®ã¿ãèšè¿°ããŸããæšæºã¯LLã䜿çšããŠCASãå®è£
ããããšãæå³ããŸã/ SCã¯éåžžã«åçŽã§ãããéã®å®è£
ïŒCASãä»ããLL / SCïŒã¯éåžžã«éèŠã§ãã ãããã£ãŠãæšæºC ++ã©ã€ãã©ãªã®éçºè
ã®ç掻ãè€éã«ããªãããã«ãC ++ã§å°å
¥ãããæšæºåå§å¡äŒã¯ãååãšããŠããã¯ããªãŒã¢ã«ãŽãªãºã ãå®è£
ããã®ã«ååãª
compare_exchange
ã®ã¿ãå°å
¥ããŸããã
åœãã®å
±æ
ææ°ã®ããã»ããµã§ã¯ãLãã£ãã·ã¥ïŒãã£ãã·ã¥ã©ã€ã³ïŒã®ã©ã€ã³é·ã¯64ã128ãã€ãã§ãããæ°ããã¢ãã«ã§ã¯å¢å ããåŸåããããŸãã ã¡ã€ã³ã¡ã¢ãªãšãã£ãã·ã¥éã®ããŒã¿äº€æã¯ãLãã€ãã®ãããã¯ã§å®è¡ãããŸãïŒéåžžãLã¯2ã®ã¹ãä¹ã§ãïŒã ãã£ãã·ã¥ã©ã€ã³ã®å°ãªããšã1ãã€ãã倿Žããããšãã©ã€ã³å
šäœãç¡å¹ãšèŠãªãããã¡ã€ã³ã¡ã¢ãªãšã®åæãå¿
èŠã«ãªããŸãã ããã¯ããã«ãããã»ããµ/ãã«ãã³ã¢ã¢ãŒããã¯ãã£ã®ãã£ãã·ã¥ã³ããŒã¬ã³ã·ãµããŒããããã³ã«ã«ãã£ãŠå¶åŸ¡ãããŸãã
MESIãã£ãã·ã¥ã³ããŒã¬ã³ã¹ãµããŒããããã³ã«ããšãã°ïŒ[Cha05]ïŒãIntelããã»ããµã®ããã»ããµã³ããŒã¬ã³ã¹ããµããŒãããMESIãããã³ã«ïŒå€æŽ-æä»-å
±æ-ç¡å¹ïŒã¯ãå
±æã©ã€ã³ãžã®æžã蟌ã¿ããšã«ãã£ãã·ã¥ã©ã€ã³ãç¡å¹ãšããŠããŒã¯ããéäžçãªã¡ã¢ãªäº€æã«ã€ãªãããŸãã ãã£ãã·ã¥ã©ã€ã³ã«æåã«ããŒã¿ãããŒãããããšãMESIã¯ãã®ã©ã€ã³ãEïŒæä»çïŒãšããŠããŒã¯ããŸããããã«ãããããã»ããµãŒã¯ãã£ãã·ã¥ã©ã€ã³ãžã®ããŒã¿ã®èªã¿åã/æžã蟌ã¿ãç¡å¶éã«è¡ãããšãã§ããŸãã å¥ã®ããã»ããµããã®ä»ã®ããã»ããµã®ãã£ãã·ã¥ã«ããåãããŒã¿ã«ã¢ã¯ã»ã¹ããå¿
èŠãããå ŽåãMESIã¯ãã£ãã·ã¥ã©ã€ã³ãSïŒå
±æïŒãšããŠããŒã¯ããŸãã çŸåšãä»»æã®ãã£ãã·ã¥å
ã®ãã®ãããªã©ã€ã³ã«æžã蟌ãåœä»€ã¯ãã©ã€ã³ãMïŒå€æŽæžã¿ïŒãšããŠããŒã¯ãããã®çµæãä»ã®ããã»ããµãŒã®ãã£ãã·ã¥å
ã§ãã®ã©ã€ã³ãIïŒç¡å¹åïŒãšããŠããŒã¯ãããã®çµæãã¡ã€ã³ã¡ã¢ãªããããŒã¿ãããŒãããŸãã æ¬¡ã®ã¡ã¢ã®1ã€ã§ãææ°ã®ããã»ããµã®å
éšçµç¹ã«é¢ãããã°ãããèšäºã®ç¿»èš³ãæäŸããäºå®ãªã®ã§ãMESIãããã³ã«ã«ã€ããŠè©³ããã¯èª¬æããŸããã

ç°ãªãå
±æããŒã¿ã1ã€ã®ãã£ãã·ã¥ã©ã€ã³ã«åé¡ãããå ŽåïŒã€ãŸãã飿¥ããã¢ãã¬ã¹ã«ããå ŽåïŒãããŒã¿ã®1ã€ããããã»ããµã®èгç¹ãããåããã£ãã·ã¥ã©ã€ã³ã«ããä»ã®ç¡å¹åã«å€æŽããŸãã ãã®ç¶æ³ã¯ã
åœå
±æãšåŒã°ã
ãŸã ã LL / SCããªããã£ãã®å Žåããããã®ããªããã£ãã®å®è£
ã¯ãã£ãã·ã¥ã©ã€ã³ã®èгç¹ããè¡ããããããåœå
±æã¯æ²æšã§ããããŒããªã³ã¯æäœã¯ãã£ãã·ã¥ã©ã€ã³ïŒãªã³ã¯ïŒãããŒã¯ããæžã蟌ã¿åã®ã¹ãã¢æ¡ä»¶æäœã¯ãã®ã©ã€ã³ã®ãªã³ã¯ãã©ã°ãã¯ãªã¢ãããŠãããã©ããããã§ãã¯ããŸã; ãã©ã°ãã¯ãªã¢ãããŠããå Žåããšã³ããªã¯äœæããããSCã¯falseãè¿ããŸãã Lã©ã€ã³ã®é·ããéåžžã«é·ã
ãã ãSCããªããã£ãã®èª€ã£ã
é害 ïŒãªã³ã¯ãã©ã°ã®ãªã»ããïŒã¯ãã¿ãŒã²ããããŒã¿ã«é¢é£ããªããã£ãã·ã¥ã©ã€ã³ã®å€æŽã§çºçããŸãã ãã®çµæã
livelockãååŸã§ããŸãã
ããã¯ãããã»ããµ/ã³ã¢ã100ïŒ
ããžãŒã§ããã鲿ããªãç¶æ³ã§ãã
åœå
±æãšã®æŠãã¯éåžžã«åçŽã§ããïŒç¡é§ã§ãïŒãåå
±æå€æ°ã¯ãã£ãã·ã¥ã©ã€ã³å
šäœãå æããå¿
èŠããããŸãã ããã«ã¯ãéåžžãããã£ã³ã°ã䜿çšãããŸãã
struct Foo { int volatile nShared1; char _padding1[64]; // padding for cache line=64 byte int volatile nShared2; char _padding2[64]; // padding for cache line=64 byte };
ãã£ãã·ã¥ã®ç©çæ§é ã¯ãLL / SCããªããã£ãã ãã§ãªãããã¹ãŠã®æäœïŒCASãå«ãïŒã«åœ±é¿ããããšã«æ³šæããŠãã ããã äžéšã®ç ç©¶ã§ã¯ããã£ãã·ã¥æ§é ãèæ
®ããŠïŒäž»ã«ãã£ãã·ã¥ã©ã€ã³ã®é·ããèæ
®ããŠïŒç¹å¥ã«æ§ç¯ãããããŒã¿æ§é ã調æ»ããŠããŸãã ããŒã¿æ§é ãé©åã«ïŒããã£ãã·ã¥ã®äžã«ãïŒæ§ç¯ãããšãçç£æ§ã倧å¹
ã«åäžããŸãã
CASã®çš®é¡
CASããã«å¹
ïŒããã«ã¯ãŒãCASãdwCASïŒãš
ããã«CAS ïŒDCASïŒãšãã2ã€ã®æçšãªã¢ãããã¯ããªããã£ãã«ã€ããŠç°¡åã«èª¬æããŸãã
ããã«å¹
CASã¯éåžžã®CASã«äŒŒãŠããŸããã32ãããã¢ãŒããã¯ãã£ã®å Žåã¯64ãããã64ãããã®å Žåã¯128ãããïŒæ£ç¢ºã«ã¯å°ãªããšã96ãããïŒã®2åã®ãµã€ãºã®ã¡ã¢ãªã»ã«ã§åäœããŸãã CASã®ä»£ããã«LL / SCãã¢ãæäŸããã¢ãŒããã¯ãã£ã®å ŽåãLL / SCã¯åé·ã¯ãŒãã§ãåäœããå¿
èŠããããŸãã ç§ãç¥ã£ãŠããã¢ãŒããã¯ãã£ã®ãã¡ãx86ã®ã¿ãdwCASããµããŒãããŠããŸãã ãªããã®ããªããã£ãã¯ãšãŠã䟿å©ãªã®ã§ããïŒ ABAåé¡
ã¿ã°ä»ããã€ã³ã¿ãŒã解決ããããã®æåã®ã¹ããŒã ã®1ã€ãæŽçã§ããŸãã ãã®ã¹ããŒã ã¯ãABAã®åé¡ã解決ããããã ãã«IBMã«ãã£ãŠææ¡ããããã®ã§ãåã¿ã°ãã€ã³ã¿ãŒãæŽæ°ãšäžèŽãããããšã«ãããŸãã ã¿ã°ä»ããã€ã³ã¿ãŒã¯ãæ¬¡ã®æ§é ã§èšè¿°ã§ããŸãã
template <typename T> struct tagged_pointer { T * ptr ; uintptr_t tag ; tagged_pointer() : ptr( new T ) , tag( 1 ) {} };
ã¢ãããã¯æ§ã確ä¿ããã«ã¯ããã®ã¿ã€ãã®å€æ°ãäºéã«æŽåãããå¿
èŠããããŸãã32ãããã¢ãŒããã¯ãã£ã§ã¯8ãã€ãã64ãããã§ã¯16ãã€ãã§ãã ã¿ã°ã«ã¯ã
ptr
æãããŒã¿ã®ãããŒãžã§ã³çªå·ããå«ãŸããŸãã ã¿ã°ä»ããã€ã³ã¿ãŒã«ã€ããŠã¯ãå®å
šãªã¡ã¢ãªåçïŒSMRïŒã«é¢ããæ¬¡ã®ããããã®èšäºã§è©³ãã説æããŸãããããã§ã¯ãã¿ã°ä»ããã€ã³ã¿ãŒãTåã®ããŒã¿ïŒããã³å¯Ÿå¿ãã
tagged_pointer
ïŒã«å²ãåœãŠãããã¡ã¢ãªãæå³ãããšããäºå®ã«ã®ã¿æ³šæããŸãç©ççã«åé€ïŒ
delete
ïŒããã®ã§ã¯ãªããããªãŒãªã¹ãïŒåã¿ã€ãTã«åå¥ïŒã«é
眮ããå¿
èŠããããŸãããããããå°æ¥ãã¿ã°ãã€ã³ã¯ãªã¡ã³ãããŠããŒã¿ãåé
åžãããŸãã ãããABAåé¡ã®è§£æ±ºçãæäŸãããã®ã§ããå®éããã€ã³ã¿ãŒã¯è€åã§ãããã¿ã°ã«ããŒãžã§ã³çªå·ïŒãã£ã¹ããªãã¥ãŒã·ã§ã³ã®ã·ãªã¢ã«çªå·ïŒãå«ãŸããŠããŸãã ãã®å Žåãtagged_pointeråã®åŒæ°ã«çãããã€ã³ã¿ãŒããããã¿ã°å€ãç°ãªãå ŽåãdwCASã¯æåããŸããã
2çªç®ã®ã¢ãããã¯ããªããã£ãã§ãã
ããã«CAS ïŒDCASïŒã¯ãçŸåšã¯çŽç²ã«ä»®æ³çãªãã®ã§ãããææ°ã®ããã»ããµã¢ãŒããã¯ãã£ã«ã¯å®è£
ãããŠããŸããã DCASæ¬äŒŒã³ãŒãã¯æ¬¡ã®ãšããã§ãã
bool DCAS( int * pAddr1, int nExpected1, int nNew1, int * pAddr2, int nExpected2, int nNew2 ) atomically { if ( *pAddr1 == nExpected1 && *pAddr2 == nExpected2 ) { *pAddr1 = nNew1 ; *pAddr2 = nNew2 ; return true ; } else return false }
DCASã¯ã2ã€ã®ä»»æã«æŽåãããã¡ã¢ãªã»ã«ã§åäœããçŸåšã®å€ãæåŸ
å€ãšäžèŽããå Žåãäž¡æ¹ã®å€ã倿ŽããŸãã
ãªããã®ããªããã£ãã¯ãšãŠãè峿·±ãã®ã§ããïŒ äºå®ããã®å©ããåããã°ãããã¯ããªãŒã®äºéãªã³ã¯ãªã¹ãïŒdequeãdouble-linkedãªã¹ãïŒãç°¡åã«äœæã§ãããã®ãããªããŒã¿æ§é ã¯å€ãã®è峿·±ãã¢ã«ãŽãªãºã ã®åºç€ã«ãªã£ãŠããŸãã DCASããŒã¹ã®ããŒã¿æ§é ã«é¢ãã倿°ã®åŠè¡è«æããããŸãã ãã®ããªããã£ãã¯ãããŒããŠã§ã¢ã§ãå®è£
ãããŠããŸããããéåžžã®CASã«åºã¥ããŠDCASïŒããã³äžè¬ã«è€æ°ã®
pAddr1
...
pAddrN
ã¢ãã¬ã¹
pAddr1
pAddrN
ãã«ãCASïŒãæ§ç¯ããããã®ã¢ã«ãŽãªãºã ã説æããäœåïŒããšãã°[Fra03]-ãããã®äžã§æãæåïŒ
æ§èœ

ã¢ãããã¯ããªããã£ãã®ããã©ãŒãã³ã¹ã¯ã©ãã§ããïŒ
çŸä»£ã®ããã»ããµã¯éåžžã«è€éã§äºæž¬äžå¯èœã§ããããã補é å
ã¯ãå
éšåæãããã»ããµãã¹äžã®ä¿¡å·ãªã©ãé¢äžããç¹å®ã®åœä»€ãç¹ã«ã¢ãããã¯åœä»€ã®æç¶æéã«ã€ããŠæç¢ºãªä¿èšŒãäžããŠããŸãããããã»ããµåœä»€ã®æéãæž¬å®ããŸãã [McKen05]ããæž¬å®ãè¡ããŸãã ãã®äœæ¥ã§ã¯ãèè
ã¯ããšããããã¢ãããã¯ã€ã³ã¯ãªã¡ã³ãããã³CASããªããã£ãã®æéã
nop
ïŒno-operationïŒæäœã®æéãšæ¯èŒããŸãã ãããã£ãŠãIntel Xeon 3.06 GHzïŒ2005ãµã³ãã«ïŒã®å Žåãã¢ãããã¯ã€ã³ã¯ãªã¡ã³ãã®æéã¯400 nopãCAS-850-1000 nopã§ãã IBM Power4ããã»ããµãŒ1.45 GHzïŒã¢ãããã¯ã€ã³ã¯ãªã¡ã³ãã®å Žåã¯180 nopãCASã®å Žåã¯250 nopã æž¬å®å€ã¯ããªãå€ãïŒ2005幎ïŒã§ãé廿°å¹Žéãããã»ããµã¢ãŒããã¯ãã£ã¯ããã«ããã€ãã®ã¹ããããèžã¿ãŸããããæ°åã®é åºã¯åããŸãŸã§ãããšæããŸãã
ã芧ã®ãšãããã¢ãããã¯ããªããã£ãã¯ããªãéãã§ãã ãããã£ãŠãããããã©ãã«ã§ãé©çšããã®ã¯ããªãè²»çšãããããŸããããšãã°ããã€ããªããªãŒæ€çŽ¢ã¢ã«ãŽãªãºã ãCASã䜿çšããŠçŸåšã®ããªãŒããŒããèªã¿åãå Žåããã®ãããªã¢ã«ãŽãªãºã ã«è¯ããã®ã¯æåŸ
ã§ããŸããïŒãã®ãããªã¢ã«ãŽãªãºã ãèŠãŠããŸããïŒã å
¬å¹³ã«èšãã°ãIntel Coreã¢ãŒããã¯ãã£ã®æ°äžä»£ããšã«ãCASããªããã£ããé«éåããŠããããã«æããŸãããIntelã®ãšã³ãžãã¢ã¯ãã€ã¯ãã¢ãŒããã¯ãã£ã®æ¹åã«å€å€§ãªåªåãæ³šãã§ããããã§ãã
æ®çºæ§ãšååæ§
C ++ã«ã¯ãäžå¯è§£ãª
volatile
ããŒã¯ãŒãããããŸãã æã
ã
volatile
ååæ§ãšé åºä»ãã«é¢é£ä»ããããŸã-ããã¯ééã£ãŠããŸãããããã€ãã®æŽå²çãªçç±ããããŸãã
å®éã
volatile
ã¯ãã³ã³ãã€ã©ãŒãã¬ãžã¹ã¿ãŒã«å€ããã£ãã·ã¥ããªãããšãä¿èšŒããã ãã§ãïŒæé©åã³ã³ãã€ã©ãŒã¯ãããè¡ãã®ã倧奜ãã§ããã¬ãžã¹ã¿ãŒãå€ãã»ã©ããã£ãã·ã¥ãå¢ããŸãïŒã ã€ãŸããæ®çºæ§å€æ°ã®èªã¿åãã¯
åžžã«ã¡ã¢ãªããã®èªã¿åããæå³ããæ®çºæ§å€æ°ã®æžã蟌ã¿ã¯
åžžã«ã¡ã¢ãªãžã®æžã蟌ã¿ãæå³ããŸãã ãããã£ãŠã誰ããæ®çºæ§ããŒã¿ã䞊è¡ããŠå€æŽããå Žåãããã«ãããããããŸãã
å®éã衚瀺ãããŸããã ã¡ã¢ãªããªã¢ãäžè¶³ããŠããããã äžéšã®èšèªïŒJavaãCïŒïŒã§ã¯ã
volatile
éæ³ã®ã¹ããŒã¿ã¹
volatile
å²ãåœãŠãããŠããŸãããC ++ 11ã§ã¯ããã§ã¯ãããŸããã ãŸãã
volatile
ã¯ç¹å¥ãªã¢ã©ã€ã¡ã³ããä¿èšŒãããã®ã§ã¯ãªããããŒã¿ã¢ã©ã€ã¡ã³ãã®æ£ããæ¡ä»¶ãååæ§ã«å¿
èŠãªæ¡ä»¶ã§ããããšãããããŸããã
ãããã£ãŠãC ++ 11äºæã³ã³ãã€ã©ã®å Žåãã¢ãããã¯å€æ°ã«
volatile
ãæå®ããå¿
èŠã¯ãããŸããã ããããå€ãã³ã³ãã€ã©ã§ã¯ãèªåã§
atomic
å®è£
ããå Žåã«å¿
èŠã«ãªãããšããããŸãã ãã®ãããªåºåã§ã¯ïŒ
class atomic_int { int m_nAtomic;
ã³ã³ãã€ã©ã«ã¯ã
m_nAtomic
åŒã³åºãããæé©åããããã¹ãŠã®æš©å©ããããŸãïŒåŒã³åºãã¯éæ¥çã«
this
ãéããŠè¡ãã
this
ïŒã ãããã£ãŠã
int volatile m_nAtomic
ã瀺ããš
int volatile m_nAtomic
ã
C ++ã®volatileã¡ãœããatomic
ã€ã³ã¿ãŒãã§ã€ã¹ã調ã¹ããšãããããã¡ãœããã®å€ãã«
volatile
æå®åãããããšã«æ°ä»ãã§ãããã
void store( T val ) volatile ;
ããã¯äœã§ãã
this
ãã€ã³ã¿ãŒã¯
volatile
ã§ããïŒã€ãŸããã¿ã€ã
T * volatile
ã§ããïŒïŒ äžè¬ã«ãããã¯äžå¯èœã§ã-
this
ãã°ãã°ã¬ãžã¹ã¿ã§æž¡ãããããã¯ããã€ãã®ABIã§æå®ãããŸãã å®éã«ã¯ãã¿ã€ã
T volatile *
ã§ãã
const
ã¡ãœãããšã®é¡æšã«ããããã®æå®åã¯ã
this
ãæ®çºæ§ããŒã¿ãæããŠãããã€ãŸãããªããžã§ã¯ãã®ãã¹ãŠã®ã¡ã³ããŒããŒã¿ããã®ãããªã¡ãœããã§
volatile
ã§ãããšèšããŸãã ããã«ãããã³ã³ãã€ã©ãã¡ã³ããŒããŒã¿ãžã®ã¢ã¯ã»ã¹ãæé©åã§ããªããªããŸãã åºæ¬çã«ããã®ããŒã¿ã
volatile
ãšããŠå®£èšããå Žåãšåãã§ãã
ããŠã
const
ãš
volatile
æå®åã¯å察ã§ã¯ãªããäžç·ã«ååšã§ããããšãæãåºãããŠãã ããã
atomic<T>
readã¡ãœããã®å®£èšã¯æ¬¡ã®ãšããã§ãã
T load() const volatile ;
:
const
â -volatile
â - - ,
libcds
çµè«ãšããŠãlibcdsã©ã€ãã©ãªã«ã¯äœããããŸããïŒãŸããx86 / amd64ãIntel Itaniumãããã³Sparcã¢ãŒããã¯ãã£åãã®C ++ 11ã®ç²Ÿç¥ã«åºã¥ããã¢ãããã¯ããªããã£ãã®å¥ã®èªè»¢è»å®è£
ããããŸããã³ã³ãã€ã©ãŒãC ++ 11ããµããŒãããŠããªãå ŽåïŒææ°ããŒãžã§ã³ã®ã³ã³ãã€ã©ãŒã®ã¿ããµããŒãããŠããŸã-å©çšå¯èœãªã®ã¯GCC 4.7 +ãMS Visual C ++ 2012ãClang 3.0以éïŒãlibcds
ç¬èªã®ã¢ãããã¯ããªããã£ãã®å®è£
ã䜿çšããŸããåæã«ãéåžžã®ã¢ãããã¯èªã¿åã/æžã蟌ã¿ã«å ããŠãããã¯ããªãŒããŒã¿æ§é ãæ§ç¯ããéã®äž»èŠãªã¢ãããã¯ããªããã£ãã¯CASã§ãããCASã¯ããã«ã¯ãŒãïŒdwCASïŒã§äœ¿çšãããããšã¯ã»ãšãã©ãããŸãããDCASå®è£
ïŒããã³äžè¬ã«ãã«ãCASïŒlibcds
[ä»ã®ãšãã]ããããããããå°æ¥ç»å Žããå¯èœæ§ã¯ååã«ãããŸããéåžžã«è峿·±ãããŒã¿æ§é ãæ§ç¯ã§ããŸããå€ãã®ç ç©¶ã«ãããšã[Fra03]ã¢ã«ãŽãªãºã ã«ããDCASã®å®è£
ã¯ããªãéå¹ççã§ãããšããããšãæ¢ããã ãã§ããããããããã¯ã®ãªãäžçã§ã¯ãæå¹æ§ã®åºæºã¯çŽç²ã«åã
ã®ãã®ã§ããããšã«ãã§ã«æ³šæããŸããããã®ããŒããŠã§ã¢äžã§ããã®ã¿ã¹ã¯ã§çŸåšç¡å¹ãªãã®ã¯ãå¥ã®ããŒããŠã§ã¢äžã§ããŸãã¯å¥ã®ã¿ã¹ã¯ã§éåžžã«å¹æçã§ããããšã倿ããå¯èœæ§ããããŸãïŒåºç€ã®æ¬¡ã®èšäºã§ã¯ãã¡ã¢ãªã¢ã¯ã»ã¹ã®é åºïŒã¡ã¢ãªã®é åºïŒ-ã¡ã¢ãªããªã¢ïŒã¡ã¢ãªãã§ã³ã¹ãã¡ã¢ãªããªã¢ïŒã«ã€ããŠèª¬æããŸããåç
§ïŒ[Cha05] Dean Chandler ã¯.NETã§ã®åœå
±æãåæžã2005幎ãIntel Corporation [Fra03] Keir FraserPractical Lock Freedomã2004; æè¡å ±åæžã¯æåºè«æã«åºã¥ããŠããŸã 9æããã®åŸã±ã³ããªããžå€§åŠããã³ã°ã¹ã«ã¬ããžã«å²åŠå士ã®åŠäœã«ãã£ãŠK.Fraser 2003[McKen05]ããŒãã¹ã»ããŒãã«ããããŒã«McKenneyããžã§ããµã³ã»ãŠã©ã«ããŒã«ã®ã¹ã±ãŒã©ãã«ãªåæã®ããã®å®çšçãªæžå¿µãã€ã±ã«ã«ãã£ãŠ[Mic04] Maged åäžåèªåœä»€ã䜿çšããABA鲿¢ãIBM Research Reportã2004ããã¯ããªãŒã®ããŒã¿æ§é éå§ããåºæ¬ïŒ
äžïŒ
å€ããïŒ