Atomic이란

devlcw·2024년 6월 14일
3
post-thumbnail

Atomic (원자적 연산 타입)

아토믹이란 원자적 연산 타입이다. 다음과 같은 특징이 있다.

  • 기본 타입 단위에서 thread-safe 연산을 보장한다.
  • lock-free이다.

보면 알다시피 lock-free이기 때문에 연산 속도가 기존 Mutex나 세마포어 등등 구현보다 훨씬 빠르다. 이유는 코드로 구현하는 구현체가 아니라 아토믹 연산이 CPU 자체 연산 중 하나이기 때문이다. 그래서 다른 쓰레드에서 변경되는 중간 과정을 확인하지 못한다.

아토믹은 간단한 정수형들같은 기본 타입만 제공한다.

Memory Ordering

앞에 설명했던 lock-free인 것을 반대로 말해보면 아토믹은 연산 순서를 정할 수 없다. 그래서 중간에 아토믹의 연산 순서를 보장해주는 Memory Ordering이 들어간다.

종류는 다음과 같다.

  • Relaxed: 가장 낮은 순위, 연산 간 순서를 보장해주지 않고 단순히 thread-safe만 보장한다.

  • Release: 해당 메모리 오더링을 가진 연산이 발생한 이후에 다른 연산들이 발생하는 것을 보장한다. 즉, Release 연산이 완료된 후에 모든 후속 연산이 관찰될 수 있다는 것을 의미한다.

  • Acquire: 해당 메모리 오더링을 가진 연산이 발생하기 이전에 다른 연산들이 발생했음을 보장한다. 즉, Acquire 연산이 시작되기 전에 모든 이전 연산이 완료되었음을 보장한다.

  • AcqRel: Release 연산과 Acquire 연산을 합친 것으로, 이전의 모든 연산이 발생한 후에 이 연산이 시작되고, 이후의 모든 연산이 이 연산이 완료된 후에 발생함을 보장한다.

  • SeqCst: Sequentially Consistent의 약자로, 가장 강력한 메모리 순서 보장을 제공한다. 모든 스레드에서 모든 메모리 연산의 순서를 동일하게 유지하도록 보장한다.

실제 사용에서

위 종류만 보고는 한번에 이해하기가 쉽지 않다.
보통 Release는 쓰기 연산에서, Acquire는 읽기 연산에서 일어나고 AcqRel은 복잡한 연산, CAS(Compare And Swap), 읽고 쓰는 연산 등에서 일어난다.

Compare And Swap이란 특정 조건 비교 후 값을 바꾸는 연산을 말한다. 값을 비교하려면 읽고, 값을 바꾸려면 써야하니까 AcqRel이 적절한 메모리 오더링인 것이다.

SeqCst 메모리 오더링은 순차적 실행인 것처럼 여러 쓰레드에서 연산 순서를 보장해준다.

반례

lock-free라고 lock을 안 쓰고 오직 아토믹으로만 연산을 처리하려고 한다면 오히려 오버헤드가 발생할 수 있다.

  1. 잦은 동일 아토믹 변수 접근
    아토믹은 분명 CPU 연산이기 때문에 빠르다. 하지만 잦게 접근하다 보면 캐시 라인 동기화가 일어나서 오버헤드가 커질 것이다. 이런 잦은 접근이 필요할 때에는 아토믹보단 lock이 더 효율적이다.

  2. 복잡한 연산
    복잡한 연산을 아토믹 연산으로 처리하려고 하면, 여러 개의 아토믹 연산을 조합해야 하므로 코드가 복잡해지고, 성능도 저하될 수 있다. 복잡한 연산을 수행할 때는 락을 사용하여 임계 구역을 설정하고, 한번에 연산을 처리하는 것이 더 효율적일 수 있다.

참조

profile
모든 스택에는 이유가 있다

1개의 댓글

comment-user-thumbnail
2024년 7월 5일

전문적이시네요

답글 달기