暗記メーカー
ログイン
멀코 5장 non-blocking 알고리즘 - list
  • ユーザ名非公開

  • 問題数 84 • 10/20/2023

    記憶度

    完璧

    12

    覚えた

    31

    うろ覚え

    0

    苦手

    0

    未解答

    0

    アカウント登録して、解答結果を保存しよう

    問題一覧

  • 1

    set을 배열이 아닌 링크드리스트로 구현하는 이유는?

    최댓값을 모르기 때문이다.

  • 2

    성긴 동기화의 장점은?

    구현이 쉽다.

  • 3

    성긴동기화의 단점은?

    성능이 안좋다.

  • 4

    성긴 동기화를 사용하면 data race는 100% 사라진다. ( O / X )

    O

  • 5

    왼쪽 위에부터 빈칸을 채우시오.

    왼쪽 glock.lock(); glock.unlock(); glock.unlock(); 오른쪽 glock.lock(); glock.unlock(); glock.unlock(); 아래 glock.lock(); glock.unlock(); glock.unlock();

  • 6

    이것은 무슨 동기화인가?

    성긴동기화

  • 7

    pred = &head;가 lock 밖에 있는 이유는?

    read only 메모리이기 때문에 data race가 아니기 때문이다.

  • 8

    new/delete는 data race가 없다. ( O / X )

    O

  • 9

    멀티스레드 실무에서 new/delete를 잘 사용하지 않는다. 이유는?

    내부적으로 locking이 구현되어 있기 때문이다.

  • 10

    세밀한 동기화는 성긴 동기화의 어떤 점을 보완하고자 나왔는가?

    list 전체를 잠그는 것이 아니라 노드 개별로 잠궈서 병렬성을 높이기 위해 나온 것이다.

  • 11

    세밀한 동기화에서는 node의 ( )를 변경할 경우에는 반드시 lock()을 얻은 후 변경해야 한다.

    next field

  • 12

    세밀한 동기화의 주의점은?

    Add()와 Remove() 시점의 pred, curr가 가리키는 노드는 locking이 되어 있어야 한다., head부터 node 이동을 할 때, lock을 잠그면서 이동해야 한다.

  • 13

    세밀한 동기화를 통해 발견한 것은?

    스레드 개수가 늘어날수록 빨라진다. 물론 어느정도 되면 다시 느려진다.

  • 14

    세밀한 동기화는 어떤 곳이 바틀넥이 되는가?

    head

  • 15

    성긴 동기화 영어로 쓰시오.

    coarse-grained synchronization

  • 16

    세밀한 동기화를 영어로 쓰시오.

    fine-grained synchronization

  • 17

    낙천적인 동기화를 영어로 쓰시오.

    optimistic synchronization

  • 18

    게으른 동기화를 영어로 쓰시오.

    lazy synchronization

  • 19

    비멈춤 동기화를 영어로 쓰시오.

    nonblocking synchronization

  • 20

    주석에 답하시오.

    Add() 1: prev->lock(); 2: curr->lock(); 3: prev->unlock(); 4: curr->lock(); 5: prev->unlock(); 6: curr->unlock(); 7: prev->unlock(); 8: curr->unlock(); Remove() 1: prev->lock(); 2: curr->lock(); 3: prev->unlock(); 4: curr->lock(); 5: prev->unlock(); 6: curr->unlock(); 7: prev->unlock(); 8: curr->unlock(); Contains() 1: prev->lock(); 2: curr->lock(); 3: prev->unlock(); 4: curr->lock(); 5: prev->unlock(); 6: curr->unlock(); 7: prev->unlock(); 8: curr->unlock();

  • 21

    성긴 동기화와 세밀한 동기화 중 어떤 것이 더 성능이 좋은가?

    성긴 동기화

  • 22

    세밀한 동기화의 성능 저하의 원인은?

    lock(), unlock()이 너무 빈번하다.

  • 23

    세밀한 동기화는 리스트가 ( ) 경우 성능이 매우 떨어진다.

    길어지는

  • 24

    낙천전 동기화는 세밀한 동기화의 어떤 것을 보완하기 위해 나왔나?

    잠금의 획득과 해제가 너무 빈번하여 이동 시 잠금을 하지 않지 않기 위해 나온 아이디어이다.

  • 25

    낙천적 동기화는 Remove()한 노드를 ( )하지 않는다.

    delete

  • 26

    낙천적 동기화에는 ( ) 검사를 추가한다.

    validation 조건

  • 27

    낙천적 동기화에서 제거된 노드를 delete하지 않는 이유는?

    재사용되면서 어떻게 사용될지 모르기 때문이다.

  • 28

    validation 조건 검사에서 하는 것은?

    잠겨진 pred와 curr가 제거되지 않았는지, pred와 curr 사이에 다른 노드가 끼어들지 않았는지

  • 29

    validation 조건 검사에서 pred와 curr 사이에 다른 노드가 끼어들지 않은 것을 어떻게 확인할 수 있는가?

    pred->next == curr 이면 다른 노드가 끼어들지 않은 것이다.

  • 30

    volidation에서 다시 돌 때 다른 스레드가 pred, curr를 삭제하거나 중간에 노드를 끼울 수 있는 확률은? 이유는?

    전혀 없다. locking을 하고 검사를 하기 때문이다.

  • 31

    validate()에서 pred와 curr가 리스트에 존재하는지 어떻게 확인할 수 있는가?

    다시 처음부터 검색해서 원래 pred, curr로 다시 올 수 있는지 확인한다.

  • 32

    낙천적 동기화 알고리즘의 문제점은?

    다른 스레드들이 pred와 curr를 계속 수정하는 경우 계속 재시도를 하면서 기아를 겪을 수 있다.

  • 33

    낙천적 동기화에서 기아가 발생할 확률은 리스트의 길이가 길어질수록 확률이 올라간다. ( O / X )

    X

  • 34

    빈칸에 알맞은 것을 적으시오.

    add() validate(pred, curr) false true contains() validate(pred, curr) curr.key == key

  • 35

    성긴 동기화는 스레드가 늘어남에 따라 성능 변화가 있다. ( O / X )

    X

  • 36

    낙천적인 동기화가 싱글 스레드에서도 성긴 동기화보다 2배 느린 이유는?

    링크드 리스트에서 성능에 가장 영향에 미치는 것은 검색이다. 성긴 동기화는 한 번 검색하는데, 낙천적 동기화는 처음에 한 번 검색하고 validate 하면서 한 번 더 검색하기 때문에 2배 느리다.

  • 37

    낙천적인 동기화에서 발견한 것은?

    스레드 개수가 늘어남에 따라 싱글 스레드보다 성능이 더 좋아지는 것을 확인했다.

  • 38

    게으른 동기화는 낙천적 동기화의 어떤 부분을 보완하고자 나왔는가?

    낙천적 동기화는 코어의 개수가 많지 않으면 성능이 좋지 않다. 이것을 개선하고자 나온 것이 게으른 동기화이다.

  • 39

    게으른 동기화의 핵심 아이디어는?

    validate()가 노드를 처음부터 다시 순회하지 않고 수행

  • 40

    게으른 동기화에서 pred와 curr의 잠금은 여전히 필요하다. ( O / X )

    O

  • 41

    contains는 ( )이기 때문에 wait-free 알고리즘으로 변환할 수 있다.

    read-only

  • 42

    게으른 동기화에서 추가된 것은?

    marked 필드

  • 43

    게으른 동기화에서 marking은 실제 제거보다 반드시 ( ) 수행한다.

    먼저

  • 44

    빈칸을 채우시오.

    node == pred pred.next == curr node = node.next

  • 45

    빈칸을 채우시오.

    validate() !pred.marked && !curr.marked && pred.next == curr contains() curr = curr.next; curr.key == key && !curr.marked

  • 46

    게으른 동기화의 remove()이다. 빈칸을 채우시오.

    curr.marked = true;

  • 47

    게으른 동기화가 제대로 돌아가는 것은 어떠한 명제로 인해서인가?

    marking 되어 있지 않은 모든 node는 실제 리스트에 존재하는 살아있는 node이다. 해당 명제가 참이기 때문이다.

  • 48

    게으른 알고리즘은 넌블럭킹 알고리즘이다. ( O / X )

    X

  • 49

    게으른 동기화는 싱글 스레드에서 돌리는 것보다 빨라지는가?

    빨라진다. 스레드가 하나일 때는 더 느리지만 이 세상에 싱글코어 컴퓨터는 없다.

  • 50

    게으른 동기화의 단점은?

    블럭킹 알고리즘이다., 메모리 릭이 있다.

  • 51

    게으른 동기화에서 메모리 릭을 없애기 위해 그냥 delete를 하면 안되는 이유는?

    재사용하면서 오동작할 수 있기 때문이다.

  • 52

    게으른 동기화에서 메모리 릭을 해결하기 위해서는 언제 delete를 해야 하는가?

    아무도 remove된 node를 가리키지 않을 때, remove 시점에서 중복실행 중인 모든 method의 호출이 종료되었을 때

  • 53

    shared_ptr은 reference counter 증감을 atomic하게 구현한다. ( O / X )

    O

  • 54

    shared_ptr이 메모리 해제를 어떻게 자동으로 하는지에 대해 설명하시오.

    shared_ptr을 생성할 때 reference counter도 같이 할당해서 이 카운터를 증가하고 감소하면서 0이 되면 해제한다.

  • 55

    shared_ptr 게으른 동기화가 제대로 동작하지 않는 이유는?

    shared_ptr 객체를 load, store하는 것이 atomic이 아니기 때문이다.

  • 56

    shared_ptr 게으른 동기화는 모든 스레드 개수에서 잘 돌아가는가?

    싱글 스레드에서만 잘 돌아가고 멀티스레드에서는 죽는다.

  • 57

    성긴 동기화, 세밀한 동기화, 낙천적 동기화, 게으른 동기화 중 싱글 스레드에서 성능이 좋은 것 순으로 나열하시오.

    성긴 동기화, 게으른 동기화, 낙천전 동기화, 세밀한 동기화

  • 58

    성긴 동기화, 세밀한 동기화, 낙천적 동기화, 게으른 동기화 중 멀티스레드로 갈수록 성능 향상에서의 좋은 것 순으로 나열하시오.

    게으른 동기화, 낙천적 동기화, 성긴동기화, 세밀한 동기화

  • 59

    atomic shared_ptr은 잘 돌아가는가?

    잘 돌아간다. 하지만 성능이 엉망진창이다.

  • 60

    멀티스레드에서 shared_ptr은 절대 사용하면 안된다. ( O / X )

    X

  • 61

    Atomic shared_ptr의 성능이 좋지 않은 이유는?

    내부적으로 mutex를 사용하고 또한 하나의 lock으로 실행되기 때문이다.

  • 62

    멀티스레드에서 성능이 필요 없는 곳에 shared_ptr을 사용하고 싶다면 어떤 것을 사용해야 하는가?

    local atomic shared ptr

  • 63

    stl은 멀티스레드에서 사용해도 된다. ( O / X )

    X

  • 64

    lock을 사용하지 않으면 non-blocking 알고리즘이다. ( O / X )

    X

  • 65

    wait-free 알고리즘이라도 lock-free 알고리즘이 아닐 수 있다. ( O / X )

    X

  • 66

    해당 코드를 넌블럭킹으로 바꿔라.

    if (dataReady == false) return false; temp = g_data;

  • 67

    CAS를 사용하면 모든 싱글스레드 알고리즘들을 lock-free 알고리즘으로 변환할 수 있다. ( O / X )

    O

  • 68

    해당 코드를 넌블럭킹으로 고쳐라.

    while (true) { int old_sum = sum; int new_sum = old_sum + 2; if (true == CAS(&sum, old_sum, new_sum)) break; }

  • 69

    CAS를 사용하면 lock-free 알고리즘이 되는데 어려운 이유는?

    CAS는 2개의 변수에 동시에 적용할 수 없기 때문이다. 따라서 CAS를 두 번 나누어서 해주어야 하는데 그러면 그 사이에 다른 스레드가 끼어들 수 있다. 난이도가 상승한다.

  • 70

    게으른 동기화가 넌블럭킹으로 가는 지름길인 이유는?

    critical section이 충분히 짧아졌기 때문이다.

  • 71

    비멈춤 동기화 Add의 구현에서 다른 스레드가 *pred를 Remove하면 어떻게 해야 하는가?

    pred의 marking을 확인하면서 변경해야 한다.

  • 72

    비멈춤 동기화 Add의 구현에서 다른 스레드가 *pred, *curr 사이에 새로운 노드를 끼워 넣으면 어떻게 해야 하는가?

    pred와 next가 curr인 것을 확인하면서 변경해야 한다.

  • 73

    비멈춤 동기화에서 double CAS를 사용하지 못하여서 어떠한 방법을 사용했는가?

    한 장소에 주소와 marking을 동시에 저장했다.

  • 74

    double CAS처럼 사용하기 위한 한 장소에 주소와 marking을 동시에 저장하는 것은 어떻게 가능한가?

    우리의 컴퓨터가 64비트라고 그 비트를 다 사용하지 않는다. 이 중에 안 쓰는 비트를 사용하여 가능하게 한다.

  • 75

    비멈춤 동기화에서 Remove 시 제거를 시도하고 실패했을 때를 대비해 어떻게 정책을 수정했는가?

    마킹이되었지만 remove되지 않은 노드가 있는 있을 수 있다.

  • 76

    비멈춤 코드의 find()이다. 빈칸을 채우시오.

    pred.next.comparedAndSet(curr, succ, false, false);

  • 77

    비멈춤 동기화의 add(), remove()의 빈칸을 채우시오.

    add() find(head, key) new AtomicMarkableReference(curr, false) pred.next.compareAndSet(curr, node, false, false) remove() find(head, key) curr.next.attemptMark(succ, true) pred.next.compareAndSet(curr, succ, false, false)

  • 78

    우리가 만든 lock-free 알고리즘에 shared_ptr을 사용할 수 없는 이유는?

    그냥 포인터가 아닌 합성 포인터를 사용했기 때문이다.

  • 79

    EPOCH의 장점과 단점은?

    성능이 좋다. 메모리 재사용에 stopation이 생길 수 있다.

  • 80

    Lock free free list 기법을 발전 시킨 알고리즘은?

    EPOCH

  • 81

    EPOCH에서 chrono를 사용하지 않고 Epoch counter를 사용하는 이유는?

    Epoch를 사용하기에 정밀하지 않다. 읽고 쓰는 오버헤드가 크다. 데이터 사이즈가 크다.

  • 82

    EPOCH에서 'Thread Epoch Counter[My_Thread_ID] = 0;' 해당 코드가 의미하는 것은?

    검색 대상이 아니다. 일종의 최적화 시켜주는 코드

  • 83

    EPOCH의 단점은?

    어느 한 스레드의 thread epoch counter가 증가하지 않을 경우 메모리 릭이나 다름 없다.

  • 84

    EPOCH에는 각 스레드들은 자신만의 memory pool(free list)을 관리한다. ( O / X )

    O