로보넥스
2018-03-19 06:18:01
83
10279

자바의 실상..


자바..

좋은 개발도구임은 자명하다.

나도 2000년에 자바애플릿게임으로부터

j2me, 이제는 없는 그 카테고리.

java-rmi, wipi-jlet, skvm, android등

자바 또는 유사기술, 이걸 걍 뭉탱이로 자바로 부르는.

그 직군에서 일해왔다.


“코드의시인들”이란 카페를 만들어 기존의

자바에서 구현하지 못한 유사fbo를 지원하기 위해

pngnc를 만들어 배포하기도 했고, 자바로 런처나

릴레이서버를 만들어 서비스시키기도 했다.


그러나 도구는 걍 도구다. 존경의 대상이 되면 안된다.

자바의 가장 큰 아이러니는 크로스플랫폼이 망가진 것에

있다. 안드로이드앱이 ios에서 돌아가나? jar파일을

인터넷에서 받으면 윈도우OS에 자바가 기본설치

되어있나? 물론 안드로이드는 썬의 제임스고슬링이

만든 그 놈은 아니지, vm도 달빅이라는 이상한 놈이고.

썬은 망해서 오라클에 인수당했고 고슬링은 배타고 있지.


그래. 자바는 망한 플랫폼이야. 클론좀비가 되어버렸지.

pc에서 jdk 겨우 설치해서 돌아가는 졸라 안이쁜 그놈은

원래 원조지만 그건 중요하지 않고 대중들에게 자바는

안드로이드를 말하고, 그 모든 애들은 호환이 안되고.

컴파일실행하면 CPU를 100%활용하는데

이 세상엔 없는 크로스플랫폼-자바의 슬로건에 취해서

50%도 활용못하고 있지. 2중 3중으로 파싱하느라.


개발환경이 좋은가? 좋지.

이클립스를 말하는게 아니지. 안드로이드sdk를 말하는거.

그러나 그건 언어스펙에서 오는 즐거움이 아니라

ide의 성능문제임. 게다가 vs가 더 좋아 아직은.


자바도 메모리릭, 크래시가 비일비재하고.

자바가 메모리를 한정없이 먹고 빨리 뱉어주지 않아서

다른 바이너리 프로세스들이 씨껍하고 있고.

게다가 느리고, api가 너무 고수준이라 할 수 있는 일이

많이 없다는걸 느끼지. 고수가 되면.

그리고 자바도 결국 네이티브 so파일을 요구해. jni.


근데 더 웃긴건. 널리 알려진 cpu는 2개진영 밖엔

없다는 거지. 인텔과 암. c++은 바이너리 빌드가

수십개 준비해야하고 java는 원샷올킬이 되어야 맞는데

오히려 자바는 OS에 기본설치가 막혀서 크로스플랫폼이

안되고 c++은 2개만 준비하면 되는 셈이지.


그리고 가장 큰 아이러이는 이런 생각을 가진 내가

과거에 카페활동으로 자바의 신이라 불렸을 만큼

왕성한 자바진영 개발자였다는 거지.


그리고 이렇게 말하지.

저는 자바도 하고 C++도 하고 C#도 해요..^^


1
1
  • 댓글 83

  • 로보넥스
    2018-03-19 06:34:57

    글쎄.. jar를 더블클릭해서 진짜 실행이 될지

    7-zip이 열릴지 OS의 경고가 뜰지는.. 잘 모르겠고

    좀 아는 아재들은 bat을 작성할 겁니다^^


    그리고 언제부턴가 자바란

    단지 안드로이드를 뜻하는 별칭이 되어버렸죠.


    1
  • fender
    14k
    2018-03-19 08:06:00
    ...api가 너무 고수준이라 할 수 있는 일이 많이 없다는걸 느끼지. 고수가 되면.
    ...가장 큰 아이러이는 이런 생각을 가진 내가 과거에 카페활동으로 자바의 신이라 불렸을 만큼 왕성한 자바진영 개발자였다는 거지

    전 실력이나 재능없는 개발자가 발전을 못하는 것보다, 능력있는 분들이 편견이나 자신에 대한 과대평가 때문에 스스로 벽을 만들고 갇히는 것이 더 안타깝더군요.

    8
  • John84
    2k
    2018-03-19 08:23:19

    제주변에서는 자바 할줄 아는건 jsp, 서버를 할줄 아는거고

    안드로이드는 자바가 아니라는 듯이 이야기 하던데

    저랑 전혀 다른 세계에 살고 계산가봐요 ㄷㄷㄷ

    0
  • 욥욥욥
    892
    2018-03-19 08:36:18

    로보넥스님 정말 범접할 수 없는 엄청난 고수이십니다 그이름 기억하겠습니다!



    됐죠?

    어디서 자바개발자들한테 크게 당하셨나요

    이제 그만하시죠..

    0
  • pppak
    437
    2018-03-19 08:38:49

    새로운 언어, OS를 만드신분들이 이런 얘기를 하면 그런 철학을 가지고 만들었구나 하겠는데요...

    0
  • ktsedd
    6k
    2018-03-19 09:14:23 작성 2018-03-19 09:14:58 수정됨

    ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

    언어하나 만들어보셔도될듯

    범접할수없는 경지 ㄷㄷ

    0
  • 즈루시
    12k
    2018-03-19 09:16:24 작성 2018-03-19 09:19:41 수정됨

    이쯤되면 생업을 고소고발로 먹겠단 소리

    휀님들 각도기 챙기세요

    냄새가 심하게 납니다 에잇 퉤

    1
  • 마니
    977
    2018-03-19 09:23:17

    그리고 가장 큰 아이러이는 이런 생각을 가진 내가

    과거에 카페활동으로 자바의 신이라 불렸을 만큼

    왕성한 자바진영 개발자였다는 거지.


    아아.. 이건 『C언어라는 거다. 
    너네같은 자바 개발자들은 이해를 못하는 물건이지.
    나같은 로보넥스에겐 별거아니지만..?(먼산) 

    2
  • 퓨리오사
    2k
    2018-03-19 09:24:03

    자바가 안드로이드라는 별칭이라는 소리는 자바 개발자이지만 처음 들어보는 소리네요.


    0
  • zepinos
    19k
    2018-03-19 09:31:05

    일주일 정도동안 게시판이 평온했었는데...새벽부터 다시 시작이군요.


    0
  • ....
    2018-03-19 09:34:57

    덕분에 개발자가 절대 해서는 안될 생각을 알게되네요

    다른 의미로 감사합니다.

    0
  • 앙앙이
    3k
    2018-03-19 09:42:18

     안 보신 분들을 위하여 아래 글 링크합니다.

    아... 분명히 경고하는데 "눈 버릴 수 있습니다."


    ---------------- 부분 인용

    "보넥스 그는 누구인가....... " 참고 주소 : http://www.gamecodi.com/board/zboard.php?id=GAMECODI_Talk&no=22449


    혹시 모르는분을 위해 말씀드리면 ,  그는 전설입니다 ....



    참고로  그가 만든 Array  즉 Var 클래스는    백터의 랜덤억세싱과 , 리스트의 삽입 삭제 속도 , 맵의 검색속도 모두
    O(1) 자료구조를 만들었으며 , 왜 STL 이, 쓰레기처럼, vector,list,map,deque  등등으로 , 여러개로 나누었는지 모르겠다고 주장해오신분입니다

    ------------- 

    "보넥스님 컨테이너 데브피아에 올라왔네요;" 참고 주소 : http://www.gpgstudy.com/forum/viewtopic.php?t=20631&start=0&postdays=0&postorder=asc&highlight=


    // 근접용 빠른참조 
    INT Distance = Index - FastIndex; 
    if(-10 < Distance && Distance < 10) 
    switch(Distance) 
    { 
    case -9: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev->Prev->Prev->Prev->Prev->Prev; 
    case -8: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev->Prev->Prev->Prev->Prev; 
    case -7: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev->Prev->Prev->Prev; 
    case -6: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev->Prev->Prev; 
    case -5: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev->Prev; 
    case -4: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev; 
    case -3: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev; 
    case -2: FastIndex = Index; return FastData = FastData->Prev->Prev; 
    case -1: FastIndex = Index; return FastData = FastData->Prev; 


    1
  • 로보넥스
    2018-03-19 09:46:49

    아.. jsp. 서블릿이 있었군요.

    사용자가 직접 실행하는게 아니라 원소스멀티유즈도 아니고

    API도 다르지만, jsp의 존재의미는 인정하겠습니다^^


    단지 PC에서 자바 응용프로그램의 존재이유는 거의 없다는 것이고.

    모바일은 안드로이드때문에 극적으로 회생을 했지만,

    원소스멀티유즈는 이미 물건너갔고, 구글조차 NDK를 밀고 있다는 겁니다.


    상황이 이렇다는 경력자 1인의 의견입니다~!

    다른 생각을 가지실 수도 있구요. 납득이 안되는 것도 아닙니다.

    내 인생은 내가 결정하고 내가 책임지는 각자도생이라

    초심자 여러분이 어떤 언어를 배우고 나아갈지에 대한

    일반론이 아닌 특수론이라고 여겨주세요^^


    0
  • ktsedd
    6k
    2018-03-19 09:49:08

    팩맨소스ㅋㅋㅋㅋㅋㅋㅋㅋㅋ아 저건 첨보네요

    0
  • ....
    2018-03-19 09:51:30

    왜 운영자는

    로보넥스님을 탈퇴시키지않는 거죠?


    앗 이 말 계속하면 제가 탈퇴당하나요?

    0
  • 애리밍
    3k
    2018-03-19 09:55:47

    흠...여전히 틀에 박힌 얕은 사고로 똥글을 싸지르고 있네요...

    0
  • error-404
    972
    2018-03-19 10:07:45


    // 근접용 빠른참조 
    INT Distance = Index - FastIndex; 
    if(-10 < Distance && Distance < 10) 
    switch(Distance) 
    { 
    case -9: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev->Prev->Prev->Prev->Prev->Prev; 
    case -8: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev->Prev->Prev->Prev->Prev; 
    case -7: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev->Prev->Prev->Prev; 
    case -6: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev->Prev->Prev; 
    case -5: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev->Prev; 
    case -4: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev; 
    case -3: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev; 
    case -2: FastIndex = Index; return FastData = FastData->Prev->Prev; 
    case -1: FastIndex = Index; return FastData = FastData->Prev; 
    case 0: return FastData; 
    case 1: FastIndex = Index; return FastData = FastData->Next; 
    case 2: FastIndex = Index; return FastData = FastData->Next->Next; 
    case 3: FastIndex = Index; return FastData = FastData->Next->Next->Next; 
    case 4: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next; 
    case 5: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next->Next; 
    case 6: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next->Next->Next; 
    case 7: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next->Next->Next->Next; 
    case 8: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next->Next->Next->Next->Next; 
    case 9: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next->Next->Next->Next->Next->Next; 





    월요일 아침부터 웃으면서 시작할수있겠네요! ㅋㅋㅋ

    3
  • yamanin
    1k
    2018-03-19 10:12:26

    개발자가 시각이 편협하신지... 참

    10년도 더 지난 한참 철 지나 IO핸들링 따위에 파묻혀 헤어나질 못하시나요.

    여기서 주구장창 자바 느리다고 해봐도 소용없어요.

    자바는 이미 쓰임이 너무 많아요. C++보다 느린것따위는 문제가 되지 않을정도로

    개념적으로나 기술적으로 성숙한 문화에요.


    남들이 총/칼, 탱크만들때, 아주 빨리 돌도끼 만들어서 빨리 만들수 있으니까.

    맨손으로 시작해서 만들어 싸우면 돌도끼가 빨리만들수 있어서 이기긴 하겠네요.

    내가 이긴다고 계속 우기시면 되요.

    0
  • ㅇㅈㅇ
    3k
    2018-03-19 10:15:12

    api가 너무 고수준이라 할 수 있는 일이

    많이 없다는걸 느끼지. 고수가 되면..


    언어를 떠나서 이게 고수가 할말? 

    솔직히 어떤언어든 고수까지 안가고

    그냥 중급정도만 해도 기본 API로 해결안되서 수정하거나 

    직접 만들어야 될일은 비일비재함. 


    API 없으면 자기가 만들면 되지 

    꼭 남이 만든 API쓰면서 말이 많음.

    1
  • 로보넥스
    2018-03-19 10:23:53

    일단, 팩맨소스라 부릅시다 저걸.. ㅎㅎ

    10년도 더 된 소스이긴 하지만 선입견없이 잘 짠 소스예요.

    저는 10년전에도 프로그래밍 잘 했거든요..^^v


    Var라고 부르는 가변배열을 현재의 뺄셈트리가 아닌

    링크드리스트로 구현해보던 버전에서 랜덤엑서스가 목표였지만

    실제로 사용자는 귀차니즘에 의해서 인접참조가 많다는 사실을 발견하고

    링크드리스트구조상에서 해당 문제에 대하여 가장 손실이 적고(구간조사 딱 한번)

    가장 최적화 적중률이 높은 코드입니다.


    일반적인 다른 프로그래머 같으면 같은 상황에서 저런 코드가 필요함을

    느낀다고 하여도 감히 쪽팔려서 짜지 못할 코드이지만, 전 기계적으로 짠 겁니다.

    최대손실 최대효율을.


    기이한 코드는 외국소스보면 무지하게 많습니다.

    GIT이 대표적이겠네요. 토발즈형님의^^


    0
  • 로보넥스
    2018-03-19 10:26:54

    그리고 한번 물어봅시다.

    원소스멀티유즈라는 목표를 달성하고 있는

    자바분야가 뭐가 있죠? ㅎㅎ


    메인개발자도 사라지고 회사도 사라진 마당이고

    유사품만 즐비하고 OS에 기본탑재도 아닌 상황에 무슨 개발할 꺼리가 있죠?


    그냥 사이드로 스크립트짜듯이 해서 붙여서 한 프로그램을 만들 순 있겠지만.

    이제, 그 자리는 파이썬 꺼랍니다~^^


    0
  • 로보넥스
    2018-03-19 10:28:11

    글고 내용없는 인신공격 같은건 관두세요..

    나잇값 쪽팔려요.


    0
  • 마니
    977
    2018-03-19 10:30:57

    팩맨 소스 항상 보면서 궁금한건데 걍 포문돌리는거랑 성능차이나나요?


    0
  • 로보넥스
    2018-03-19 10:34:09

    당연히 차이가 납니다. 비교연산 매번 들어가죠.

    게다가 10년전의 컴파일러입니다.


    딱 저 상황을.

    저거보다 더 좋게 짤 수 있는 사람 있어요?


    0
  • 마니
    977
    2018-03-19 11:09:57

    ㅎㅎ 노드 10개 밖에 안움직이는 소스에서 for문 비교가 무슨 의미가 있을까요 ㅎㅎ

    미천한 스크립트 개발자는 이해가 잘안됩니다 ㅎㅎ

    0
  • 로보넥스
    2018-03-19 11:12:36

    저게 STL같은 거거든요. 템플릿 컨테이너.

    속도가 아주아주 중요한 코드랍니다^^


    저기 한두줄이 프로그램에 입히는 득실이 어마어마함.


    0
  • 냉동참치
    408
    2018-03-19 11:46:08

    원소스멀티유즈는 이미 물건너갔고, 구글조차 NDK를 밀고 있다는 겁니다.

    >>오라클에 고소미 먹어서 그런거 아니었나요? 이게 원소스멀티유즈하고 먼상관있는지 모르겠습니다.

    0
  • 스피드스타
    432
    2018-03-19 12:22:27 작성 2018-03-19 12:49:13 수정됨

    로보넥스님 나름대로 내공 지대로 쌓으신 분임..

    다들 까니까 나도 까자하는 마인드로 인신공격성 발언은 자제를..

    개인적으로는 팩맨 소스도 로보넥스님 말처럼

    그 코드의 존재 의미가 부여될 상황이 있을수있어보임..

    일단 제가 말하고싶은건, 깔땐 까더라도 근거를 가지고 까달라는거에요 ㅋㅋ

    그래야 지대로 토론 배틀이 열릴듯함 ㅋㅋㅋ

    0
  • Timai
    69
    2018-03-19 12:41:40

    또 시작이네

    0
  • 반지노
    67
    2018-03-19 13:11:04

    추천했습니다.

    혹시 블로그같은거 하시나요?

    주로 C#이랑 java만 하던 개발자입장에서 님의 생각과 철학에 굉장히 호기심이 가네요.

    0
  • aeba
    2018-03-19 13:18:35 작성 2018-03-19 13:33:33 수정됨

    솔직히 로보님 글에 뭘 더 쓰기 싫었는데 어떻게 볼때마다 틀린 부분이 보여서 지적을 하지 않을 수가 없게 만드는지 신기합니다. 팩맨소스에 관해서 써볼게요.



    로보님이 피하려고 했던 for문에서 추가 더하기와 비교 연산으로 인한 성능 페널티는 원래부터 존재하지 않았습니다.


    그 이유는 현대 CPU에서는 코어 하나에 ALU가 여러개 달려있기 때문인데요



    사진에서 보시듯이 먼 옛날얘기가 된 코어2에는 두개였는데 하스웰 가서는 4개인가? 달려있는거로 알고 있습니다. 그 후는 잘 모르겠는데 줄진 않았겠죠 ㅎ


    저 말은 독립적인 데이터에 대해서는 프로그래머의 의도적인 개입 없이 하나의 코어 내부에서 병렬처리를 하는 거라 보시면 됩니다.


    그러면 for문의 사용으로 인해 추가되는 연산인 { 1. 인덱스 업데이트, 2. 목표값과의 비교 } 가 어차피 해야되는 연산인 { 메모리 엑세스해서 다음 노드의 값 가져오기 } 보다 짧다면 속도의 차이가 없게 됩니다. 쉽게 알 수 있지만 힙에서 랜덤한곳에 어디 하나 엑세스하는것 보단 캐시안에 있는 값을 대상으로 연산 두개 하는게 훨씬 짧게 걸리겠죠.


    따라서 팩맨소스를 그대로 for문으로 대체해도 인덱스 업데이트(++i) 랑 다음 노드로 포인터를 업데이트하는게 동시에 이루어지고 둘 사이의 의존관계가 없기 때문에 시간상의 차이는 없습니다.


    이렇게 이득은 없는 팩맨소스지만 단점은 있습니다. 코딱지만큼이긴 하겠지만 바이너리 크기가 늘어나는건 물론이고, 범위를 벗어난 인덱스에선 추가적인 쓸데없는 연산이 붙죠. 물론 제일 큰건 소스에 쓸데없는게 붙었다는 점이라고 생각해요.
    4
  • ktsedd
    6k
    2018-03-19 13:23:04

    음 여기댓글에 인신공격하시는분이있었나요

    팩맨소스도 과거글 링크글에 댓글분이 팩맨같다고해서 그런거에요 오해마세요 ㅋㅋ

    0
  • 로보넥스
    2018-03-19 14:11:06

    애바님>

    ++i가 아니라 링크드리스트입니다. 포인터예요.

    왜 의존관계가 없나요.. ㅎㅎ


    0
  • 로보넥스
    2018-03-19 14:13:20

    스피드스타님>

    감사합니다만.. 내공이랄건 없습니다-_-)


    빈지노님>

    블로그는 그다지 없습니다.

    기분내킬때 또는 빌드같은거 시간날때, 주 커뮤니티에 글쓰는 게

    취미라면 취미입니다^^


    0
  • aeba
    2018-03-19 14:18:31 작성 2018-03-19 14:25:44 수정됨

    로보넥스//

    링크드리스트인건 아는데 스위치를 써서 팩맨모양을 만든게 for문에 있는 가산이든 감산이든 그 연산을 피하려고 짠게 아닌가요? 그럼 스위치는 왜 쓰시는 건가요?


    링크드리스트에서 랜덤엑세스를 for문을 가지고 구현하려면 포인터의 위치와 루프횟수(i)는 연관이 없기 때문에 코어 안에서 병렬로 처리한다는 뜻입니다. 일부러 자주 쓰는 케이스를 따로 떼어낼 필요가 없다는 말이에요.

    0
  • dog foot
    2018-03-19 14:25:18

    @aeba 지금 로보넥스님 코드가 링크드리스트에서 n번째 데이터를 읽으려는 게 맞죠? 이건 보통 for-loop 안에서 병렬화되기 어려울 것 같습니다. i번째 iteration이 i-1번에 loop-carried, data dependency가 있으니까요.

    loop unrolling을 통해서 정확히 로보넥스님이 하신 일을 컴파일러가 할 거 같긴 합니다. 이 경우에는 index variable update 하는 비용, 테스트 하고 브랜치 하는 비용은 그만큼 줄일 수 있거든요. 한데 이것도 for loop의 테스팅이 예컨대 while(!node) 이런 식이라면 할 지 안 할지 잘 모르겠네요.

    기본 아이디어는 어차피 -10에서 10 정도 범위 내에서 접근은 unrolling을 하자는 건데 비판의 핵심은 -10과 10이라는 수가 얼마나 합리적이냐는 거겠죠.

    0
  • dog foot
    2018-03-19 14:26:38
    @aeba switch의 구현을 생각해보세요. 저렇게 연속된 값이면 O(1) 테이블 룩업입니다. 연속된 값이 아니면 binary search하기 때문에 N case에 대해 N번 branch하지 않고 O(lgN) 번 합니다.


    0
  • dog foot
    2018-03-19 14:29:30
     @aeba 저는 안 된다고 생각합니다. 컴파일러는 약간 보수적이거나 시간을 엄청나게 많이 들여서 정확하게 일 처리를 할 수밖에 없습니다. 사람은 당연히 이 룹에 read only만 있다고 알고 있지만, 행여 다른 쓰레드가 이 포인터에 의해 포인팅되는 메모리를 건드릴 가능성은 없을까요? 제가 컴파일러 디자이너라면, 일단 포인터를 dereference 해서 뭘 읽어오는 순간 보수적으로 응대할 것 같습니다만..


    0
  • 로보넥스
    2018-03-19 14:30:10

    내용에 연관성이 없으면 for문을 병렬처리하도록 컴파일되는 건 대충 알고 있지요..

    근데 저 팩맨코드는 연관성이 있잖아요.


    0
  • 로보넥스
    2018-03-19 14:33:45

    네 저도 도그풋님 견해랑 비슷합니다.

    저렇게까지 할 수도 있고 아닐 수도 있지만 안할 가능성도 있고.


    왜 -10에서 10이냐.. 그건 더 이상 도저히 쓰지를 못하겠어서.. ㅋㅋ


    원래 저 컨테이너의 의도는 랜덤엑서스거든요.

    절차적 억세스가 아니라요.

    근데 평소에 +1, -1식의 접근으로 쓰시는 분들이 상당히 많은데

    랜덤엑서스를 위한 전체과정에 아깝잖아요. 근데 딱 옆이동만 고려할려다 보니

    10정도까지는 점프를 지원하자 싶었습니다.


    0
  • aeba
    2018-03-19 14:33:47

    ??????? 무슨 말씀을 하시는건지 핀트가 안맞는거 같습니다만.


    스위치가 느리다는 소리를 하는게 아닙니다. 글을 다시 한번 읽어보세요. for의 오버헤드가 없다는 뜻입니다.


    그리고 노드가 위치한 메모리 주소가 for문 안에서 쓸 i 의 값과 연관이 있다는 말인가요? 무슨뜻인지;;


    0
  • aeba
    2018-03-19 14:34:50

    설마,


    설마,


    
    case 1: FastIndex = Index; return FastData = FastData->Next; 
    case 2: FastIndex = Index; return FastData = FastData->Next->Next; 
    case 3: FastIndex = Index; return FastData = FastData->Next->Next->Next; 
    case 4: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next; 
    case 5: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next->Next; 
    case 6: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next->Next->Next; 
    case 7: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next->Next->Next->Next; 
    case 8: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next->Next->Next->Next->Next; 
    case 9: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next->Next->Next->Next->Next->Next; 


    모든 줄의 실행코스트가 똑같다는 소리를 하시는 건가요?

    0
  • 로보넥스
    2018-03-19 14:36:04

    님이 말씀하신 병렬적 처리는


    for(int i = 0; i < n; ++i) sum += i;

    같은 코드나 된다는 소리죠. 앞뒤 연관성이 없는.


    0
  • 로보넥스
    2018-03-19 14:36:42

    코스트는 당연히 다르죠.. ㅎ


    0
  • aeba
    2018-03-19 14:42:56 작성 2018-03-19 14:50:32 수정됨

    어차피 스위치 문을 써도 일일히 따라가야 하고 그 외의 액세스는 루프를 써야되면 왜 스위치 문을 쓰냐는거죠. 루프가 느리지 않는데.


    @dogfoot

    컴파일러는 왜 나오는지 잘 모르겠네요(한마디도 한적 없는데)


    i++랑 Node = Node -> Next 와의 어떤 의존관계가 있는지도 모르겠네요.

    0
  • aeba
    2018-03-19 14:46:02

    for(int i = 0; i < n; ++i) sum += i;

    이건 연관이 있죠. ++i 랑 sum += i 랑 순서가 명확히 정해지지 않으면 경쟁조건이죠;;;;;




    i++랑 Node = Node -> Next 는 순서가 명확히 정해지지 않아도 상관없다는 소립니다.

    0
  • 마니
    977
    2018-03-19 14:55:02

    @aeba

    컴퓨터 만드는 작자들이 멍청한 작자들은 아니였네요.

    switch성능과 for성능 차이가 안나는군요!

    0
  • dog foot
    2018-03-19 14:59:49 작성 2018-03-19 15:07:45 수정됨
    @aeba 자동으로 병렬화를 해주는 주체가 하드웨어인가요 컴파일러인가요? 제 상식으로 그건 컴파일러의 일입니다.

    먼저 님이 말한 포룹은 디펜던시가 없습니다. 컴파일러가 바보도 아니고 그 정도는 충분히 핸들링 해요. 하지만 포인터 접근은 다릅니다. 컴파일러 입장에서는 Node*가 예컨대 펑션 패러미터로 올 때, 컴파일러는 그게 뭘 가르키는지 잘 모릅니다. 왜냐하면 대부분의 컴파일러가 펑션 단위로 먼저 컴파일 하고 나중에 inter-procedural optimization을 같은 파일 내에서 하고, 가장 마지막으로 이따금 어떤 컴파일러는 프로그램 스코웁에서 최적화를 합니다. 따라서 핵심은 컴파일러가 Node*를 볼 때, 유저가 의도한 것 외에도 모든 가능한 케이스를 다 충분히 생각하게 된다는 거죠. 컴파일러는 첫째, 런타임 체크 코드를 잔뜩 넣어서 병렬화를 한 버전과 아닌 버전을 만들거나, 둘째, 그냥 포기합니다. 제가 보기엔 gcc도 링크드 리스트 억세스를 auto-vectorize 안 할 거 같습니다. 그게 첫번째 포인트에요. 그래서 님이 주장하신 컴파일러든 뭐든 단순히 코어가 여러 개라서 포 룹이 병렬화된다는 것은 대부분의 상용/비상용 컴파일러에서 유효하지 않다고 생각합니다. 저희 팀에는 컴파일러 벡터라이제이션만 전담하는 엔지니어가 있는데 이 모듈이 하는 일은 대부분은 그냥 벡터라이즈가 안 되니 어떻게든 룹을 쪼개든 뭐든 해서 되게 만들어 보는 건데, 현실적으로는 퍼블리쉬 하는 벤치마크의 핫 룹에서만 조금 벡터라이즈를 하게 합니다. 그리고 컴파일러 프레임웤이 있다면, 그래서 행여라도 님이 주신 sum 하는 룹의 벡터라이즈가 구현 안 된 컴파일러가 있다면 저도 할 수 있습니다.

    두번째도 비슷한데, 제가 aeba님의 얘기를 오해한 이유는 컴파일러가 그 룹을 벡터라이즈 할 수 없다고 봤기 때문입니다. 그 경우 당연히 next 연산도 병렬화가 안 됩니다. 따라서 for loop에 들어가는 테스트와 브랜치를 아낄 수 없고요. switch로 룹 언롤링을 저렇게 해놓으면 코드까지 가는데 O(1)이죠. 다음에는 그 기나긴 코드를 수행하는 건데, 그 부분에선 제가 착각한 게 맞고, 메모리 레퍼런스 하는 수는 포룹일 때나 스위치 케이스에 길게 쓸 때나 차이가 없습니다.

    벡터라이즈가 되는지 안 되는지 보시려면, gcc-7 정도 가져다가 컴파일 할 때, -c와 함께 -march=AVX512-skylake -O3 해 보세요. 다음에 objdump -d my.o 또는 -d -S 로 보시면 생성된 어셈블리가 보입니다. 일반적으로 vector register는 이름이 xmm이나 무슨무슨mm 이니까 그 룹 코드 가셔서 벡터라이즈가 되는지 안 되는지 보세요. gcc 버전이 낮을수록 아마도 vectorize 될 가능성도 더 낮을 거고요.




    1
  • aeba
    2018-03-19 15:02:50
    @마니
    일반화할 수 있는건 아닙니다만 for루프같은건 워낙많이 쓰니까 의존성이 없는 경우엔 하드웨어적으로도 많은 최적화가 가능한가 봅니다.

    Premature optimization is the root of all evil이라고 하죠.

    로보님이 스위치 쓴 룩업 오퍼레이터랑 아닌 오퍼레이터랑 따로 떼서 실제 도는 프로그램에서 성능비교한거 있나요? 그냥 스위치 쓰면 빠르겠지하고 막연히 기대하고 그렇게 쓴거 같은데요 제가 보기엔?
    0
  • 마니
    977
    2018-03-19 15:07:26

    @aeba

    10만개 이상 노드를 돌려야 유의미한 결과값이 나오지 않나요?

    근데 현실적으로 10만개 이상을 하드코딩한다? 음.. 모르겠네요


    0
  • guyv
    1k
    2018-03-19 15:09:36

    적진에서 닥돌 광도발.. 그립다... wow 재밌었는데...


    1
  • dog foot
    2018-03-19 15:11:32
    @aeba 보아하니 답을 꽤 무례하게 다네요? 저야말로 님 상식은 별로 관심없고 지금 나름 고급 지식을 말도 안 되는 대우에 전달해 주는 거 같은데... 하드웨어에 ALU를 넣든 프로세서를 넣든 VLIW로 만들든 수퍼 스케일러를 하든, 복잡한 소스 코드가 바로 병렬화가 된다고 생각하십니까? 기본적으로 하드웨어 레벨의 병렬화에 대해서 이해가 전혀 없으신 것 같군요. 룹 레벨을 풀어서 병렬화 해주는 건 하드웨어 인스트럭션을 이용하긴 하지만 기본적으로 컴파일러 옵티마이저의 일입니다. gcc internal에서 auto-vectorization 찾아보세요. 중간 코드를 찍어 보면 vector 코드가 찍힙니다. 하드웨어가 아니고 컴파일러가 하는 일이고, 그건 이 분야의 ABC에요. 모르고 답 달 때는 최소한 예의를 갖추시기 바라겠고 앞으로 님 글에 답글 하는 멍청한 짓은 안 하겠습니다. 그럼 이만.


    0
  • aeba
    2018-03-19 15:12:33

    @dogfoot

    1. 일단 글을 읽어보시고요.

    2. 전 링크드리스트를 벡터나 배열같이 만드는 일에 대해선 언급한적 없고요

    3. 네 스위치는 위와같은 상황에선 일반적으로 테이블 룩업이 돼서 O(1)인거 알고 있고요

    4. 스위치를 버리고 for루프만 써도 성능상의 차이가 없다. 그 이유는 현대 CPU의 구조상 ++i와 i < N 실질적인 소요시간이 0이기 때문이다 라는 말을 하려는 겁니다.

    0
  • aeba
    2018-03-19 15:15:42 작성 2018-03-19 15:19:30 수정됨

    우선 무례한 댓글 적은거에 대해선 죄송합니다.


    하지만 조금 답답했던 점은 이해해 주셨으면 합니다.


    고급 정보의 전달은 감사합니다만, 전 지금 컴파일러에 대해서 얘기하려는게 아닙니다.


    싱글 스레드 내에서, 프로세서 내에서 데이터의 의존성을 찾아서 상호 의존성 없는 인스트럭션을 코어 한개 안에서 병렬로 처리한다는 얘기를 하는겁니다. 이건 GCC와는 관계 없는 일입니다.


    전 처음부터 컴파일러를 언급한 적도 없었고, 제 주장에 대한 근거는 컴파일러랑 전혀 상관없습니다.


    댓글을 다실때는 상대방의 주장을 먼저 확실히 파악해 주시면 감사하겠습니다.

    0
  • dog foot
    2018-03-19 15:18:47
    @로보넥스 한 번 100만개의 아이템이 있는 리스트를 index 룩업하고 많이 한다고 가정해 보면, 매 룩업마다 -10과 10 사이에 있는지 아닌지 테스트를 해야할 것 같은데요? 그런데 최악의 경우 룩업이 그 레인지 밖에서만 일어난다면, 이 일종의 캐슁은 없는 게 낫죠. 반대로 항상 이 레인지 안에서만 일어난다면 당연히 좋은 거고요. 현실은 그 중간의 어디겠구요. 제 생각엔 사이즈, 레인지 테스팅이 늘 필요한 점을 극복할 만큼 일반적으로 가치가 있는 코드는 아닌 것 같습니다만, 그건 응용 영역마다 다르고 저도 실험을 해본 적이 없고 하니.. 혹시 그런 류의 실험을 해보셨는지 물어보고 싶었습니다. 그런데 위의 제 댓글에서는 표현이 좀 잘못 되었네요.
    0
  • 우주고래
    21
    2018-03-19 15:19:20

    정말 궁금해서 그러는데, 이렇게 심도 있는 논쟁을 하시는 분들은

    어떤 소프트웨어를 개발 중이신가요?

    0
  • dog foot
    2018-03-19 15:29:05

    @aeba 네... 그래서 제가 똑같은 얘길 몇 번 설명해 드리는 거에요.우리가 코드를 어셈블리로 하나요, 고급 언어로 하나요? 당연히 고급 언어죠?


    그럼 제가 여쭤볼게요. 로보넥스님이 언롤링을 한, 원래 룹이 있는데, 그 룹을 컴파일러가 그냥 예사롭게 병렬화 없이 번역했다 치죠. 그게 하드웨어에 들어가면 자동으로 functional unit 여러 개에서 vector 연산으로 처리된다고 생각하세요? 그러면 그건 "하드웨어"가 병렬화를 하는 거죠.


    그렇지 않다는 겁니다. 지금 님의 얘기하시는 게 SIMD라면, 그건 하드웨어에 명시적으로 SIMD instruction을 줘야 합니다. 즉, scalar version 컴파일러가

     add R1, R2, R3 로 z = x+y를 번역하면, 그건 SIMD로 결코 받아들여지지 않고 그냥 보통의 scalar 연산으로 처리됩니다. 이게 병렬화되는 건 다른 주위의 관련 없는 인스트럭션들과 함께에요. 예컨대 바로 위에 a = b - c 가 있었다면, 같이 들어갈 수 있습니다. 이 경우에도 하드웨어가 speculation을 해주는 경우와 컴파일러가 의존관계 없는 애들이 한 사이클에 같이 하드웨어 유닛에 수행되러 들어갈 수 있도록 인스트럭션을 배치해주는 경우, 그 둘을 모두 하는 경우가 있습니다만, 이건 님이 얘기한 것과는 다른 거죠.

    룹 바디를 병렬화해주는 기법은 소프트웨어 파이프라인이니 auto-vectorization이니 하는 것들인데, 이건 대부분이 컴파일러가 보고 하드웨어가 그냥 병렬화하면 되게끔 뭔가를 해줘야만 합니다. SIMD라면 룹을 먼저 unrolling 하고, iteration 사이의 loop carried dependency가 없다고 확인한 다음, unrolling 한 코드를 묶어 SIMD IR로 바꾸고 그걸 SIMD instruction으로 생성합니다. 그래서 auto-vectorization 없이 나온 코드와 다른 코드가 나오고, 그래야 그 하드웨어가 SIMD를 수행할 수 있어요.


    소프트웨어 파이프라인도 마찬가지인데, 이것도 룹을 컴파일러가 언롤한 다음, 하드웨어가 예컨대 (단순한 설명을 위해) 연속된 네 개의 어셈블리 명령을 집어서 동시에 수행한다고 가정했을 때, 어셈블리의 순서를 잘 바꿔서 룹 바디가 이전 룹의 명령어와 함께 동시에 수행될 수 있도록 조정해 주는 기법이에요. 이것도 당연히 생성된 코드가 달라서 하드웨어에 들어가는 인풋이 다릅니다.

    그래서 직접 어셈블리로 코딩하지 않는 이상, 대부분 님이 아는 룹 병렬은 컴파일러의 작업이에요.



    0
  • dog foot
    2018-03-19 15:29:32
    @우주고래 컴파일러와 툴 체인 개발합니다.


    1
  • dog foot
    2018-03-19 15:34:00

    @aeba 저도 아키텍쳐 전문가는 아니지만, 컴퓨터 아키텍쳐를 알면 테스팅에 코스트가 거의 없다는 얘기 안 하실 텐데요. 여전히 나이브하게 작성된 코드의 브랜치는 문제가 됩니다. 어쨌든 이 정도 하죠.

    0
  • aeba
    2018-03-19 15:34:56

    많이 배워갑니다. 가르침 주셔서 감사합니다.


    무례했던건 죄송합니다.


    많이 부끄럽지만 대들었던건 지우지는 않고 두겠습니다.

    1
  • dog foot
    2018-03-19 15:35:04 작성 2018-03-19 19:08:45 수정됨

    그리고 코어는 펑셔널 유닛이 아니에요. 코어는 thread level parallelism이라서 싱글 쓰레드 룹 병렬화와는 상관이 없습니다.

    p.s. 이 부분 향후에 수정합니다. SIMD 하고 코어수는 관계없습니다. 다만 컴파일러가 룹을 보고 룹이 패러렐라이즈 될 수 있는 경우, 어떤 최적화는 쓰레드를 여러 개 만들어 룹 이터레이션을 배당해 주기도 합니다. 자동으로 하기도 하고 OpenMP 같이 pragma를 기반으로 해주시고 하고요. 이런 최적화는 쓰레드를 만들어야 하니까 상당히 비싸서 당연히 20번 도는 룹에 대해선 안 합니다. 안 하기 위해서 정적 분석을 하거나 dynamic checking routine을 넣고 parallel, sequential loop을 각각 생성해서 분기하게 합니다.


    0
  • 로보넥스
    2018-03-19 15:55:43

    그래서 저 위의 코드보다 더 빠른 코드를

    만들 수 있는 겁니까? 아닌 겁니까? ^^

    똑같은 상황에서.

    0
  • dog foot
    2018-03-19 16:08:23
    @로보넥스 상황 따라 다르죠. 아이템이 100만개고 index로 iterate over 하면서 하나씩 보면 위의 코드가 느립니다. 왜냐하면 100만 - 21개에 대해 매번 레인지 테스팅을 하니까요. 그게 아니라 index access를 많이 하지만 대부분 그 레인지 안에 들어간다면 위의 코드가 빠릅니다. 저라면 상황에 따라 코드 생성기로 더 많은 룹을 언롤링하겠습니다. 그래서 기본적으로 실험이 보통 필요한 거죠. 아닌가요?


    0
  • 로보넥스
    2018-03-19 16:16:24

    일단 조건이 "if(-10 < Distance && Distance < 10)"인 겁니다.

    그걸 벗어나면 저건 특수처리이고, 원래의 랜덤엑서스 알고리즘에 따라

    선택하게 됩니다. 그럴려고 만든 컨테이너였으니까요..


    즉, "-10 < Distance && Distance < 10"안에서

    더 빠른 코드를 만들거나

    속도가 동일하며 저 정리된 코드를 만들 수 있냐는 거죠..


    0
  • dog foot
    2018-03-19 16:35:17 작성 2018-03-19 16:36:05 수정됨

    @로보넥스 네, 그거는 압니다. 대충 얘기해서 v[i] 를 구현하는 코드가 이거라고 해보죠. 이때 i가 -10에서 10 사이인 것이 알려져 있다면, 코드 생성기를 쓰시면 관리가 좀더 편하겠지만 어쨌든 이 코드 자체는 저는 괜찮다고 생각합니다. 그런데 행여 로보넥스님이 아닌 제가 이 라이브러리를 가져다가
     for (int i = 0; i < N ; i++)

        f(v[i]);
    와 같이 쓰면서 N >> 10 이면 어떻게 되냐는 거죠. 그러면 이 v[i]의 경우 레인지 테스트를 N번 하죠. 그리고 N-10개의 참조에 대해서는 이 테스팅이 주는 이점이 하나도 없습니다. 원래의 랜덤 억세스 알고리즘 + 불필요한 체킹 입니다. 당연히 더 느린 코드가 되겠죠. 실제로는 어플리케이션에 따라 여기저기서 주어진 입력마다 조금 다르게 v[i]를 사용할 텐데, 그게 어느 쪽 극단에 가깝냐에 따라 그 코드가 적합한지 아닌지 결정된다는 얘기죠. 이 코드의 단점은 관리, 생산성 등등이고 장점은 성능이어야 되는데, 성능에 장점이 없는 응용 영역에서는 쓰이면 안 되겠죠.

    0
  • 로보넥스
    2018-03-19 18:39:16

    네.. 뭔가 도그풋님의 설명은 전문용어가 너무 많아서..

    이해가 어려움.. ^^;;


    뭔가 맞는 말씀이신듯.. ㄷㄷ..


    0
  • dog foot
    2018-03-19 18:40:08
    @마니 기우에서 남기는데 for 하고 switch 당연히 차이 납니다. 다만 10번밖에 안 돌면 그 자체로 크진 않겠죠. 그러나 그 크지 않은 차이가, 이 루틴을 10만번쯤 수행하다 보면 큰 차이로 바뀝니다. aeba님이 잘못 알고 계셨던 거니 위의 제 댓글들 읽어보세요. 다만 이 copy and paste 코드는 읽기 어렵고 관리도 하기 쉽다고 할 순 없죠. 제 이해로 일반적인 규칙은 성능이 조금 떨어져도 읽고 관리하기 쉬운 코드를 짜고, 성능이 바로 여기 때문에 문제가 된다면 로보넥스님이 하신 것처럼 쥐어짜는 게 말도 안 될 정도는 아니라고 봅니다.


    0
  • jja
    2k
    2018-03-19 23:28:25

    결론 관리 어렵고 장점도 그닥..고수 앞에 아무도 댓글을 달지 못함..컴파일러라니!!!

    0
  • 마니
    977
    2018-03-20 01:13:28

    @dog foot

    @aeba

    재밌는 토론 잘봤습니다. 100프로 이해는 안되더라도 얻어가는게 많네요 감사합니다

    0
  • ktsedd
    6k
    2018-03-20 09:11:24

    헐 고수님이 한바탕 휘저어 놓고 탈퇴하심

    0
  • samchon
    380
    2018-03-20 14:55:32
    // 근접용 빠른참조 
    INT Distance = Index - FastIndex; 
    if(-10 < Distance && Distance < 10) 
    switch(Distance) 
    { 
    case -9: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev->Prev->Prev->Prev->Prev->Prev; 
    case -8: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev->Prev->Prev->Prev->Prev; 
    case -7: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev->Prev->Prev->Prev; 
    case -6: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev->Prev->Prev; 
    case -5: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev->Prev; 
    case -4: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev->Prev; 
    case -3: FastIndex = Index; return FastData = FastData->Prev->Prev->Prev; 
    case -2: FastIndex = Index; return FastData = FastData->Prev->Prev; 
    case -1: FastIndex = Index; return FastData = FastData->Prev; 
    case 0: return FastData; 
    case 1: FastIndex = Index; return FastData = FastData->Next; 
    case 2: FastIndex = Index; return FastData = FastData->Next->Next; 
    case 3: FastIndex = Index; return FastData = FastData->Next->Next->Next; 
    case 4: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next; 
    case 5: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next->Next; 
    case 6: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next->Next->Next; 
    case 7: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next->Next->Next->Next; 
    case 8: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next->Next->Next->Next->Next; 
    case 9: FastIndex = Index; return FastData = FastData->Next->Next->Next->Next->Next->Next->Next->Next->Next; 


    음... 위에 case 1 ~ 9 까지의 코드를 보면서 든 생각이 좀 무섭네요.

    무엇을 위한 코드인지 이해는 가나, 여차하면 실수하기 딱 좋은 코드라서 매우 불안해 보입니다.

    그래서 저라면 이렇게 바꾸어 쓰겠습니다.


    -----------------------


    template <typename Node, INT N>
    struct Advancer
    {
        auto operator()(Node &&node)
        {
            if constexpr (N < 0)
                return Advancer<Node, N+1>(node->prev);
            else
                return Advancer<Node, N-1>()(node->next);
        };
    };
    
    template <typename Node>
    struct Advancer<Node, 0>
    {
        auto operator()(Node &&node)
        {
            return node;
        };
    };
    
    template <typename Node, INT N>
    struct Explorer
    {
        auto operator()(Node &&node, INT index)
        {
            if (N == index)
                return Advancer<Node, N>()(node);
            else
                return Explorer<Node, N+1>()(node, index);
        };
    };
    
    if (-10 <= Distance && Distance <= 10)
        FastData = Explorer<Node, -10>(FastData, Distance);


    Var 클래스(?) 코드를 이렇게 고치면,

    FastData->Next->Next->... 구문에 비해 퍼포먼스 손실보는 것 일절 없고,

    Explorer 객체도 꼬리재귀 함수인지라 case 구문에 비해 크게 손해볼 것도 없구요.


    오히려 구문도 깔끔해지고, 실수할 여지도 줄어드니 좀 더 낫지 않을까 합니다.

    1
  • 로보넥스
    2018-03-20 15:00:19

    네 저런 방법이 있죠^^ 알긴 압니다만.

    코드량도 많고, 가독성도 떨어지고..

    팩맨코드도 줄맞춤되어서 실수여지는 거의 없습니다^^


    0
  • 로보넥스
    2018-03-20 15:00:42

    삼촌프레임워크로 유명한 삼촌님이시군요^^

    0
  • 로보넥스
    2018-03-21 13:36:43

    아! 그렇구나..

    Distance는 상수화 불가능한 진짜 변수죠.


    0
  • samchon
    380
    2018-03-21 15:50:49

    @S.K.K. 본래 보넥스님의 코드에서도 Index 에 대해 switch ~ case 문으로 조건검사가 들어갑니다. 위 템플릿 클래스 Explorer::operator() 또한, 꼬리재귀에 해당하기에 if ~ else 문을 쓴 것 만큼의 성능은 나옵니다. 물론, switch ~ case 가 if ~ else 문에 비해 빠르다고 하나, 측정했을 때 유의미한 수준의 격차가 나오는 것은 아니니 문제될 것은 없다 생각합니다.

    0
  • 로보넥스
    2018-03-21 21:26:25

    스크크님>

    삼촌님, 스크크님 모두 수고하셨네욤..

    10년전 코드라서 큰 의미는 없습니다^^;


    게다가 글 내용과 이슈가 전혀 달라졌네요.. ㅠ


    0
  • 미치삶
    6
    2018-03-22 03:45:13

    댓글이 너무 재미있네요.

    잘읽었습니다.


    0
  • 로보넥스
    2018-03-22 11:50:34

    스스크님>


    님의 의견이 맞습니다만,

    코끼리만지기고 케바케라서 자신의 의견을 주장할 때는

    융통성을 인정하는 자세가 맞습니다. 잘 압니다.


    그러나.

    제 의견의 대부분은 소수의견입니다.

    소수의견이 대중적 견해의 성역을 깨뜨리기 위해서는

    강한 어조로 어필하는 것이 필요하다고 봅니다.

    문제를 강력하게 드러내는 일종의 퍼포먼스적인.


    왜 항상 소수의견내고, 강한어조로 말하는가?

    저도 90%이상은 대중적 견해에 휩쓸리는 인간입니다.

    그러나 대중적 견해. 누구나 인정하는 그것.

    그것을 꼭 글로 쓸 필요가 있을까요? 말안해도 다 아는데?


    그것을 꼭 글로 써야 한다면

    그것은 내가 정상입니다. 나도 정상이예요를 어필하는 행위 정도겠지요.

    저한테 그런 추임새 행위는 없어도 됩니다^^

    흔들리지 않아요^^


    0
  • 로그인을 하시면 댓글을 등록할 수 있습니다.