Кіріспе
Өз жұмысын тоқтатса, басқа тізбектердің жұмысын тоқтатпайтын тізбектегі алгоритм. Компьютер ғылымында, егер кез келген тізбектің жұмысын тоқтату немесе кідірісі басқа тізбектің жұмысын тоқтатуға немесе кідіруге себеп болмаса, онда алгоритм бұғатталмайтын деп аталады; кейбір операциялар үшін бұл алгоритмдер дәстүрлі бұғаттаушы нұсқаларға пайдалы балама болып табылады. Бұғатталмайтын алгоритм, егер жүйелік прогресске кепілдік берілсе, құлыптаусыз болады, ал әр тізбек бойынша прогресске кепілдік берілсе, күтуден бос болады. "Бұғатталмайтын" термині 2003 жылы кедергісіздік ұғымы енгізілгенге дейін әдебиетте "құлыптаусыз" терминімен синоним ретінде қолданылған. "Бұғатталмайтын" сөзі бұрынғыда телекоммуникациялық желілерді сипаттау үшін қолданылған, олар "бар қоңырауларды қайта ұйымдастыру қажеттілігінсіз" релелер тізбегі арқылы қосылысты жолтай алатын (Қосылған желіге қараңыз). Сондай-ақ, егер телефон станциясы "ақаулы болмаса, қосылысты әрқашан жасай алады" (Бұғатталмайтын минималды жайылмалы коммутаторға қараңыз).
In computer science, an algorithm is called non blocking if failure or suspension of any thread cannot cause failure or suspension of another thread; for some operations, these algorithms provide a useful alternative to traditional blocking implementations. A non blocking algorithm is lock free if there is guaranteed system wide progress, and wait free if there is also guaranteed per thread progress. "Non blocking" was used as a synonym for "lock free" in the literature until the introduction of obstruction freedom in 2003. The word "non blocking" was traditionally used to describe telecommunications networks that could route a connection through a set of relays "without having to re arrange existing calls" (see Clos network). Also, if the telephone exchange "is not defective, it can always make the connection" (see nonblocking minimal spanning switch).
Мотивация
Көп тірісті бағдарламалаудың дәстүрлі тәсілі ортақ ресурстарға қол жеткізуді синхрондау үшін құлыптарды пайдалану болып табылады. Синхрондау примитивтері, мысалы, мютекстер, семафорлар және сындық секциялар – бағдарламашының кодтың белгілі бір бөлімдерінің бір мезгілде орындалмауын қамтамасыз ететін барлық механизмдер, егер ол ортақ жад құрылымдарын бұзуы мүмкін болса. Егер бір тіріс басқа тіріс ұстап тұрған құлыпты алуға тырысса, тіріс құлып босағанша тоқтатылады. Тірісті тоқтату көптеген себептермен қолайсыз болуы мүмкін. Оның бір себебі – тіріс тоқтатылған кезде ол ештеңе істей алмайды: егер тоқтатылған тіріс жоғары басымдықты немесе нақты уақыт міндетін орындап жатқан болса, оның ілгерілеуін тоқтату өте қолайсыз болар еді. Басқа проблемалар аз байқалады. Мысалы, құлыптар арасындағы белгілі бір өзара әрекеттесулер тұйықталу, тірі құлып және басымдықтың кері ауысуы сияқты қате жағдайларына әкелуі мүмкін. Құлыптарды пайдалану сонымен қатар параллелизм мүмкіндіктерін айтарлықтай азайтатын ірі ұсақты құлыптау мен мұқият жобалауды қажет ететін, құлыптаудың қосымша шығынын арттыратын және қателерге бейім болатын ұсақ ұсақты құлыптау арасындағы таңдауды қамтиды. Блоктау алгоритмдерінен айырмашылығы, блоктамайтын алгоритмдер осы кемшіліктерге ұшырамайды және үзіліс басқарушыларында пайдалану үшін қауіпсіз: алдын ала тоқтатылған тіріс қайта іске қосылмаса да, одан басқа да прогреске қол жеткізуге болады. Керісінше, өзара құлыптау арқылы қорғалған жаһандық дерек құрылымдарына үзіліс басқарушысынан қауіпсіз түрде қол жеткізуге болмайды, өйткені алдын ала тоқтатылған тіріс құлыпты ұстап тұруы мүмкін, бірақ бұл өзекті бөлімде үзіліс сұранысын маскировкалау арқылы оңай түзетілуі мүмкін. Құлыпсыз дерек құрылымы өнімділікті жақсарту үшін пайдаланылуы мүмкін. Құлыпсыз дерек құрылымы қатар орындауға жұмсалатын уақытты сериялық орындауға қарағанда арттырады, көп ядролы процессордың өнімділігін жақсартады, өйткені ортақ дерек құрылымына қол жеткізуді сақтап қалу үшін сериялық түрде жүйеге кірудің қажеті жоқ.
Күту еркіндігі
Күту еркіндігі – прогрестің ең күшті кедергісіз кепілі, ол жүйелік деңгейде кепілдік берілген өнімділікті аштықтан құтылумен үйлестіреді. Алгоритм күтусіз болып есептеледі, егер әрбір операцияның аяқталуына дейін алгоритмнің атқаратын қадамдарының саны шектелген болса. Бұл қасиет нақты уақыт жүйелері үшін маңызды және өнімділік шығыны тым жоғары болмаса, әрқашан пайдалы. 1980 жылдары барлық алгоритмдерді күтусіз жүзеге асыруға болатыны көрсетілді, сондай-ақ сериялық кодтан универсалды құрылымдар деп аталатын көптеген түрлендірулер ұсынылды. Дегенмен, нәтижесінде алынған өнімділік тіпті қарапайым блоктаушы жобалардан да төмен болып шықты. Кейінірек бірнеше зерттеу жұмысы универсалды құрылымдардың өнімділігін жақсартты, бірақ олардың көрсеткіштері блоктаушы жобалардан әлі де қалысқан күйде. Көптеген зерттеулер күтусіз алгоритмдерді жасаудың қиындықтарын қарастырды. Мысалы, CAS және LL/SC сияқты кең таралған атомдық шартты примитивтер жад шығындары жіптер санына пропорционалды өсетін жағдайларда, көптеген кең таралған дерек құрылымдары үшін аштықтан құтылмаған жүзеге асыруды қамтамасыз ете алмайды. Бірақ практикалық тұрғыдан алғанда, бұл шектеулер маңызды кедергі тудырмайды, өйткені әр жіп үшін ортақ жадта бір кэш жолы немесе эксклюзивті резервтеу грануласын (ARM-да 2 КБ-ға дейін) жұмсау, практикалық жүйелер үшін тым қымбат емес деп есептеледі (логикалық тұрғыдан қажетті сақтау көлемі әдетте бір сөзді құрайды, бірақ бір кэш жолындағы CAS операциялары қақтығысуы мүмкін, ал LL/SC операциялары бір эксклюзивті резервтеу грануласында қақтығысады, сондықтан физикалық тұрғыдан қажетті сақтау көлемі артады). Күтусіз алгоритмдер 2011 жылға дейін зерттеулерде де, практикада да сирек кездесетін. Алайда, 2011 жылы Коган мен Петранк CAS примитивіне негізделген күтусіз кезек құрылымын ұсынды, ол көптеген аппараттық платформаларда қол жетімді. Олардың құрылымы Майкл мен Скотттың құлыпсыз кезегін кеңейтті, ол практикада жиі қолданылатын тиімді кезек. Коган мен Петранк жариялаған келесі мақала күтусіз алгоритмдерді жылдамдату әдісін ұсынды және осы әдісті күтусіз кезекті құлыпсыз әріптесімен салыстырылатын жылдамдыққа жеткізу үшін қолданды. Тимнат пен Петранк жариялаған келесі зерттеу жұмысы құлыпсыз деректер құрылымдарынан күтусіз деректер құрылымдарын автоматты түрде жасау механизмін ұсынды. Осылайша, қазіргі таңдағы көптеген деректер құрылымдары үшін күтусіз жүзеге асырулар қол жетімді.
Қалқасыздық
Құлыптау еркіндігі жеке жіптердің аштыққа ұшырауына мүмкіндік береді, бірақ жүйелік өнімділікті қамтамасыз етеді. Алгоритм құлыптаусыз болады, егер бағдарлама жіптері жеткілікті ұзақ уақыт бойы жұмыс істеген кезде, кем дегенде бір жіп прогресс жасаса (прогресс туралы нақты анықтамасы бар болса). Барлық күтусіз алгоритмдер құлыптаусыз болады. Атап айтқанда, егер бір жіп тоқтатылса, құлыптаусыз алгоритм қалған жіптердің де прогресс жасауына кепілдік береді. Сондықтан, егер екі жіп бір мутекс құлпы немесе спин құлпы үшін бәсекелесе алса, онда алгоритм құлыптаусыз болмайды. (Егер біз құлыпты ұстап тұрған бір жіпті тоқтатсақ, екінші жіп тоқталады.) Алгоритм құлыптаусыз болады, егер процессорлардың шексіз саны операцияны шекті сандағы қадамдарда орындауға мүмкіндік берсе. Мысалы, егер процессорлар операцияны орындауға тырысса, кейбір процестер операцияны шекті сандағы қадамдарда аяқтауға мүмкіндік алады, ал басқалары сәтсіздікке ұшырап, сәтсіздік жағдайында қайтадан тырысады. Күтусіз және құлыптаусыз арасындағы айырмашылық – күтусіз операцияның әр процессор үшін басқа процессорлардың жағдайына қарамастан, шекті сандағы қадамдарда сәтті аяқталуына кепілдік беріледі. Жалпы, құлыптаусыз алгоритм төрт фазада жұмыс істей алады: өз операциясын аяқтау, кедергі келтіретін операцияға көмектесу, кедергі келтіретін операцияны тоқтату және күту. Өз операциясын аяқтау бір мезгілде көмектесу және тоқтату мүмкіндігінен қиындатылады, бірақ әрқашан аяқталудың ең жылдам жолы болып табылады. Кедергіге кездескен кезде көмектесу, тоқтату немесе күту туралы шешімді бәсекелестік менеджері қабылдайды. Бұл өте қарапайым болуы мүмкін (жоғары басымдылық операцияларына көмектесу, төмен басымдылық операцияларын тоқтату) немесе жақсы өнімділікке жету үшін немесе басымдылық операцияларының кідірісін азайту үшін оңтайландырылуы мүмкін. Дұрыс бір мезгілде көмектесу құлыптаусыз алгоритмнің ең күрделі бөлігі болып табылады және оны орындау өте қымбат: көмектесуші жіп баяулап қана қоймай, ортақ жадтың механикасының арқасында, егер ол әлі де жұмыс істеп тұрса, көмектесілген жіп те баяулайды.
progress (for some sensible definition of progress). All wait free algorithms are lock free. In particular, if one thread is suspended, then a lock free algorithm guarantees that the remaining threads can still make progress. Hence, if two threads can contend for the same mutex lock or spinlock, then the algorithm is not lock free. (If we suspend one thread that holds the lock, then the second thread will block.) An algorithm is lock free if infinitely often operation by some processors will succeed in a finite number of steps. For instance, if processors are trying to execute an operation, some of the processes will succeed in finishing the operation in a finite number of steps and others might fail and retry on failure. The difference between wait free and lock free is that wait free operation by each process is guaranteed to succeed in a finite number of steps, regardless of the other processors. In general, a lock free algorithm can run in four phases: completing one's own operation, assisting an obstructing operation, aborting an obstructing operation, and waiting. Completing one's own operation is complicated by the possibility of concurrent assistance and abortion, but is invariably the fastest path to completion. The decision about when to assist, abort or wait when an obstruction is met is the responsibility of a contention manager. This may be very simple (assist higher priority operations, abort lower priority ones), or may be more optimized to achieve better throughput, or lower the latency of prioritized operations. Correct concurrent assistance is typically the most complex part of a lock free algorithm, and often very costly to execute: not only does the assisting thread slow down, but thanks to the mechanics of shared memory, the thread being assisted will be slowed, too, if it is still running.
Қатты кедергісіздігі
Тосқауылсыздық – табиғи түрде прогреске кедергі келтірмейтін ең әлсіз кепілдік. Алгоритм тосқауылсыз болып есептеледі, егер кез келген сәтте, барлық тосқауыл тудыратын жіптер тоқтатылған жағдайда, бір жіптің оқшауланған орындалуы (яғни, тосқауыл тудыратын жіптердің тоқтатылуымен) шектеулі қадамдар саны бойынша жұмысын аяқтаса. Барлық құлыптаусыз алгоритмдер тосқауылсыз болады. Тосқауылсыздық тек жартылай аяқталған операцияны тоқтатуды және жасалған өзгерістерді кері қайтаруды талап етеді. Бір мезгілдегі көмекті тоқтату көбінесе жайпақ алгоритмдерді тудырады, оларды тексеру оңайырақ. Жүйенің үнемі тікелей құлыпталуынан сақтану – бәсекелестік менеджерінің міндеті. Кейбір тосқауылсыз алгоритмдер дерек құрылымында "сәйкестік маркерлерінің" жұбын пайдаланады. Дерек құрылымын оқитын процестер алдымен бір сәйкестік маркерін оқиды, содан кейін тиісті деректерді ішкі буферге оқиды, содан кейін екінші маркерді оқиды және содан кейін маркерлерді салыстырады. Егер екі маркер бірдей болса, деректер сәйкес келеді. Маркерлер дерек құрылымын жаңартатын басқа процесс оқыған кезде әртүрлі болуы мүмкін. Мұндай жағдайда процесс ішкі буфердегі деректерді жойып, қайтадан талпынады.