volatile과 최적화 장벽의 비교 실험

gurugio의 이미지

원문: http://asmlove.co.kr/wiki/wiki.php/gurugio/barrier_test

volatile 변수는 접근할 때마다 항상 메모리에 값을 읽거나 쓰게 됩니다.
그런데 컴파일러의 최적화 장벽도 모든 변수의 값을 메모리에 쓰거나 읽게 만드는 일을 한다고
"리눅스 커널의 이해"에서 배웠습니다.

비슷한 일을 하는것 같지만 어떤 차이가 있는지에 대해서 실험을 했습니다.

제가 내린 결론은 원문에 써있듯이 다음과 같습니다.

Quote:

최적화 장벽이 없다면 volatile 변수를 처리하는 코드 사이에도 최적화 처리를 한다. 따라서 volatile 선언은 volatile 변수를 처리하는 코드 부분만 최적화 장벽 역할을 하고, 다른 코드와는 상관이 없음을 알 수 있다.

따라서 최적화 장벽과 volatile 변수는 별개이며 volatile 변수가 최적화 장벽 역할을 하는 것은 아니라는 결론이다.


댓글

서지원의 이미지

여러가지 잘못된 부분이 있는데,

1. 최적화 장벽 이 아니라 메모리 장벽 이라고 하는게 더 맞습니다. memory barrier는 최적화를 막거나 한다기 보다는 (그런 side effect도 있겠지만) application에서 memory consistency 를 얻기 위해 쓰는거구요
2. 실험 자체도 좀 잘못되었는데, volatile을 쓰더라도 threading이나 interrupt등을 사용하지 않으면 어짜피 volatile이건 아니건 차이가 없습니다. 따라서 compiler가 smart하게 register값을 memory에 쓰고 읽는 것을 없앴을 수 있습니다. (함수 안에서 쓸데없는 계산을 하고 그 결과를 사용하지 않으면 보통 계산하는 코드 자체가 optimize되어 없어집니다)
3. 실험이 잘못되었기 때문에 결론도 잘못되었습니다. volatile keyword는 해당 변수를 읽고 쓸때에 항상 메모리에서 읽고 쓰도록 하라는 hint 입니다. (실제로 compiler가 이걸 얼마나 잘 하는지는 잘 모르겠지만...)

gurugio의 이미지


아.. 부끄럽습니다.
죄송합니다.

----
섬기며 사랑하면 더 행복해집니다.
개인 홈페이지가 생겼습니다 http://caoskernel.org
어셈러브를 개편중입니다 http://www.asmlove.co.kr

winner의 이미지

이 실험이 시작된 http://kldp.org/node/104904 의 책을 보면 최적화 장벽과 메모리 장벽에 대해서 구분하고 있습니다.

제가 assembly를 거의 몰라서 이 실험을 해석할 수가 없어 지켜보고 있었습니다만 gurugio님이 받아들인 잘못의 지적이 제가 보기엔 더 이상합니다. 책을 읽고 계신 gurugio님이 이 지적을 받아들인게 오히려 당황스럽네요.

gurugio의 이미지


rvds 에서도 최적화장벽이라는 용어를 쓰는 것 같습니다.
그리고 최적화 장벽과 메모리 장벽을 구별하고 있는 것으로 봐서
최적화 장벽을 메모리 장벽과 구별해서 사용하는게 정확한게 아닐까요?

죄송하지만 실험이 잘못되었다는 말씀을 이해하기가 어렵습니다.
volatile에 대한 정의는 저도 동일하게 생각하고 있는데요
volatile과 최적화 장벽을 비교한 것 자체가 잘못된것이라는 의미이신가요?
아니면 방법이 잘못되었다는 의미이신가요?

아니면 소스를 좀더 실질적으로 계산하는 소스로 실험하라는 의미이신가요?

좀더 자세히 말씀해주시면 다시 실험해보겠습니다.

----
섬기며 사랑하면 더 행복해집니다.
개인 홈페이지가 생겼습니다 http://caoskernel.org
어셈러브를 개편중입니다 http://www.asmlove.co.kr

서지원의 이미지

Memory barrier는 말 그대로 memory consistency 를 얻기 위해서 있는 겁니다. compiler 최적화를 막는 등의 효과가 있을 수도 있겠지만, 최적화 종류에 따라서는 영향을 안 받을 수도 있습니다.

그리고 C/C++ keyword로서의 volatile keyword를 쓸 때에는 thread, interrupt, signal등 volatile keyword가 상관있을만한 기능을 사용해야 의미가 있지 그렇지 않다면 compiler가 optimize를 해서 volatile keyword효과가 없어질 수 있습니다. 해당 기능을 쓰면서 실험을 해야 의미가 있습니다.

gurugio의 이미지


예 감사합니다.

제가 잘 이해가 안되는 것은 volatile 키워드가 상관있을만한 기능을 써야 한다고 하시는게
잘 이해가 되지 않습니다.
저는 volatile은 컴파일러가 optimize를 하지 말라고 지시하는 것으로 알고 있어서
특정 기능을 쓰면서 실험할 필요가 없다고 생각했었습니다.

그리고 메모리 장벽을 실험한 것이 아니고 GCC의 컴파일러 장벽을 실험하고자 한 것이라서
물론 최적화 종류에 따라 영향을 받을 수 있겠지만
메모리의 consistency를 실험하려고 한 것이 아닙니다.

제 생각에는 제가 실험의 목표에 대해서 정확하게 쓰지 못한 것도 문제가 된것 같습니다.
일단 원문을 다시 올려보도록 하겠습니다.

----
섬기며 사랑하면 더 행복해집니다.
개인 홈페이지가 생겼습니다 http://caoskernel.org
어셈러브를 개편중입니다 http://www.asmlove.co.kr

prio의 이미지

Quote:
그리고 C/C++ keyword로서의 volatile keyword를 쓸 때에는 thread, interrupt, signal등 volatile keyword가 상관있을만한 기능을 사용해야 의미가 있지 그렇지 않다면 compiler가 optimize를 해서 volatile keyword효과가 없어질 수 있습니다.

컴파일러가 컴파일타임에 특정 코드의 실행 환경을 개런티하는 것이 불가능 하기 때문에,
컴파일러는 무조건 volatile의 효과(?)를 내도록 코드를 생성합니다.

anfl의 이미지

grassman의 이미지

memory barrier는 CPU의 instruction reordering에 대한 부작용을 막기 위해서 사용하는 겁니다. (Intel의 경우 근래의 CPU에 out-of-order execution을 도입했기 때문에 lfence, sfence 등의 memory barrier 관련 명령이 추가된 것을 알 수 있습니다.) 이것은 당연히 컴파일러의 최적화에 영향을 주지는 않습니다. 삭제되기 전의 내용을 읽어 보았습니다만 실험 자체에 문제는 없었고 결과도 문제 없는 것으로 보였습니다. (순수하게 CPU의 영향이 아닌 컴파일러 최적화 측면에서의 실험 결과 도출입니다)

P.S. volatile이 memory barrier의 효과를 갖는가에 대해서는 이전 질문 내용에 적으려다가 사족이 될 것 같아서 적지 않았습니다만... volatile은 memory barrier 효과를 갖지 않습니다.

anfl의 이미지

어떤 느낌을 받아 지난 댓글 다신걸 몇게 읽어보았습니다.
무례하게 생각하지 않으신다면 뭐하시는 분이신지 살짝 알려주실 수 있으신지요?
다른 의도는 없고 단순히 궁금해서 그럽니다.


grassman의 이미지

별로 내세울만한 것도 없고 프로그래밍 하면서 점점 성격만 나빠지는 전형적인 회사원입니다.
고등학교 2학년 때부터 PC에서 C 언어로 프로그래밍을 시작했던지라 x86과 C 언어에 대한 얘기에는 조금 끼어 들어서 아는 척 하고 있습니다. (다른 언어는 걸음마 수준인지라 답글 달아 놓아도 별로 신뢰성은 없습니다)

anfl의 이미지

댓글들을 보면서 깊이가 였보였습니다.
그래서 누구신지 궁금했었습니다.
저도 임베디드를 합니다.
이제는 개발에 손을 끊고 다른일을 하고 있습니다.
좋은 글들 잘 읽었습니다.


gurugio의 이미지


저는 아직 리눅스 커널의 이해라는 책만 보고 있는 상황이라서
불확실한게 많습니다.
일단 다른 책들과 자료들도 더 보고 공부해야될것 같습니다.

답글에 좋은 말씀을 많이 써주셔서 글타래를 지우지는 않겠습니다.

----
섬기며 사랑하면 더 행복해집니다.
개인 홈페이지가 생겼습니다 http://caoskernel.org
어셈러브를 개편중입니다 http://www.asmlove.co.kr

bushi의 이미지

글 복구하신 뒤에 wiki 원문을 읽으니 어째서 memory barrier 논쟁이 나왔는지 이해가 되네요.

OTL

gurugio의 이미지


아직 제가 잘못 이해한 부분이 많은것 같은것 같다고 생각하고 있는 중입니다.
어떤 부분이 논쟁이 될만한지 알려주시면 좋겠습니다.

동기화 부분은 멀티코어 이해를 위해 자세히 공부하고 싶긴한데
뭐라 말할 수 없이 이해하기 어려운 부분이 많아서 골치가 아프더라구요 ;-)

----
섬기며 사랑하면 더 행복해집니다.
개인 홈페이지가 생겼습니다 http://caoskernel.org
어셈러브를 개편중입니다 http://www.asmlove.co.kr

bushi의 이미지

리눅스 커널을 보신다니 ... 이미 보셨을거라 생각하지만
http://lxr.linux.no/linux+v2.6.29/Documentation/memory-barriers.txt

http://www.linuxjournal.com/article/8211
http://www.linuxjournal.com/article/8212

'memory barrier 로 논쟁이 번진 것이 이해가 되네요'라는 말은
'그럴 수도 있다' 라는 주장의 의미가 아니라
'난데없는 memory barrier가 여기 왜 튀어나왔는지 이유를 알겠다' 라는 의미로 썼습니다.

실험에 사용하신 asm 코드는 optimization barrier 목적으로 사용하는 barrier() 죠.
사용하신 용어 '최적화장벽'이 딱히 틀리지 않고, 컴파일러에 제한된 실험과 결론이었으므로 전반적으로 공감합니다.

다만, 리눅스 커널 소스에서,
memory barrier 에 대한 특별한 고려를 하지 않아도 되는 환경(CPU)들에 대한 memory barrier 구현이 저 barrier() 로 되어 있습니다.
아마도 이것 때문에 memory barrier 논쟁으로 번진 것이 아닌가 생각합니다.

OTL

lovewar의 이미지

최적화를 무력화(volatile) 시키는 방법은 다음 두가지가 있다고 생각합니다.
1. 객체(변수)에 대한 최적화 금지 방법(volatile int vola)
2. 로직에 대한 최적화 금지 방법(asm volatile (로직) )

둘다 volatile 지시자를 붙여야 한다는 전제 조건이 있을것 같습니다.

-- 덧붙이는 글 --
잘못된 부분은 지적부탁드립니다.

gurugio의 이미지


제 생각을 말씀드리면요

1. volatile 변수를 쓰는 것은 그 변수가 사용되는 코드의 최적화를 금지
2. asm volatile (...)은 해당 어셈블리 코드를 그대로 삽입

그런데 최적화 장벽과의 차이는 전체 코드에서 컴파일러가 최적화를 실행하는 코드를
나누는 것으로 생각이 됩니다.
전체 코드가 10라인일 때 컴파일러가 10라인 전체를 고려해서 최적화를 하겠지만
만약 최적화 장벽을 5라인에 넣게되면

1~4라인을 한 덩어리로 보고 최적화 -> 모든 계산 결과를 메모리에 기록 -> (모든 변수를 메모리에서 다시 읽기) -> 6~11 라인을 최적화

이렇게 될것 같습니다.

volatile 변수는 하나의 변수만 최적화를 금지하지만
최적화 장벽은 코드 한 묶음의 최적화를 금지해서 그 코드 묶음의 뒤로는 다시 메모리를 읽어오도록 한다고
생각하고 있습니다.

----
섬기며 사랑하면 더 행복해집니다.
개인 홈페이지가 생겼습니다 http://caoskernel.org
어셈러브를 개편중입니다 http://www.asmlove.co.kr

lovewar의 이미지

Quote:

1~4라인을 한 덩어리로 보고 최적화 -> 모든 계산 결과를 메모리에 기록 -> (모든 변수를 메모리에서 다시 읽기) -> 6~11 라인을 최적화

최적화장벽이란 최적화를 잠시 중지하고 현재의 최적화된 내용을 메모리에 써라. 이렇게 이해하면 되는 건가요?
이럴경우 volatile 변수와 비교자체가 무의미한것 아닌가 하는 생각을 합니다.

최적화를 한다는 가정하에 다음과 같은 코드 만들어 봤습니다.

volatile int vola;
void foo(void)
{
   vola = 0x10;
   vola++;
 
   printf ("vola is %d", vola);  /* vola is vola + 1 */
}
 
int nonVola;
void boo(void)
{
    nonVola = 0x10;
    nonVola++;
    asm volatile("" ::: "memory");
 
     printf ("nonVola is %d", nonVola);   /* nonVola is 0x11 */
}

prio의 이미지

'최적화 장벽'은, 원래의 의도가 그러하듯이, 컴파일러에 특정된 기능입니다.
현재 논의되고 있는 asm volatile("":::"memory") 문은, gcc 컴파일러에 국한된 것입니다.
gcc가 위 인라인 어셈블리 문장을 '최적화 장벽'으로 생각하겠다는 것입니다.

저 문장은 실제로는 instruction이 공란이므로 아무 의미가 없습니다.
대신 clobber 리스트에 "memory"라고 적혀 있으므로, 이것을 기준으로 최적화 장벽의 역할을 하게 하는 것이지요.
컴파일러가 최적화를 위해 사용하는 정보 중에 가장 기본이 되는 것이 use-def 정보이기 때문에,
이 시점에서 "메모리가 뭉개졌다" 라는 정보를 컴파일러에게 주면 그 지점을 기준으로 최적화 범위가 나뉘는 것입니다.

최적화 장벽을 두었을 때 어떤 일이 벌어지는 지도 역시 컴파일러에 따라 다르게 정의됩니다.
(실제로는 거의 비슷하게 정해지는 것이 사실이지만;;)

지금 메모리 장벽이니, 변수에 대한 최적화니 라는 얘기가 자꾸 나오는 것이,
C/C++의 표준 키워드인 volatile 이 들어가면서도 비슷한 일이 벌어지기 때문인데요..
실제로 표준 키워드 volatile과 최적화 장벽과는 아무 연관이 없다고 생각하고 출발해야 헷갈리지 않습니다.

'volatile'의 사전적 의미는 '예고 없이 갑작스럽게 변하는, 휘발성인' 이라는 뜻입니다.
그렇기 때문에 변수를 매번 직접 읽고 쓰도록 코드를 생성할 필요가 있을 때 쓰는 키워드를 'volatile'로 정한 것이지요.
컴파일러가 '최적화를 하지 않는다'고 보는 것 보다, '매번 메모리를 읽고 쓰도록 코드를 생성한다'고 보는 것이 더 엄밀합니다.
매번 메모리를 읽고 쓰는 것이 성능을 떨어뜨리기 때문에 최적화를 하지 않는다고 생각하기 쉬운데,
실제로 컴파일러는 매번 메모리를 읽고 쓰도록 하는 한에서 가능한 모든 최적화를 수행합니다.

이러한 맥락 이용해서 gcc의 inline assembler가
asm 문을 '있는 그대로' 코드로 생성해야할 경우에 대해 volatile 키워드를 사용하는 것입니다.
표준이 아니므로 volatile이 아니라 임의의 키워드를 추가할 수도 있었을 겁니다.

지리즈의 이미지

최적화 장벽이 필요한 이유와 최적화 장벽이 실제 코드에 대체적으로 어떤 식으로 반영되는 가요?

There is no spoon. Neo from the Matrix 1999.

There is no spoon. Neo from the Matrix 1999.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.