사실 Six sigma는 굉장히 오래된 분야이고, 특히 software에는 잘 안맞는다고 알려져 있습니다. 하지만 18년동안의 software engineer생활에 있어서, software six sigma가 매우 도움이 많이 되고, 더욱이 여기서 익힌 통계적 지식과 방법론이 machine learning에조차 도움이 되어 이 글을 쓰게 되었습니다. 내용이 많아서 연재로 쓸 예정이니 많이 읽어 주세요.
도입. 최적화의 문제
연구소에 입사하게 된 다해봐 연구원의 이야기 입니다. 대규모의 시스템을 개발하는 연구소인데요, 지금 한참 개발이 진행중이었습니다. 시스템의 구조는 매우 간단해서 64개의 processor와 이 processor를 있는 통신 장비로 구성이 되어 있고, 모든 데이터는 통신 장비를 통해서 전송이 되어야 합니다. 처음에 전원을 키면 64개중에 하나만 먼저 시동을 하고, 이 하나가 나머지 63개에 필요한 데이터를 hard disk에서 읽어서 통신 장비를 통해서 보내는 역할을 합니다. 마치 고대의 서버/클라이언트 패턴과 매우 비슷한 구조입니다. 즉 우선 한개가 서버로 동작을 하고, 나머지 63개가 클라이언트가 되어서 서버에게 데이터를 요청하는 형태입니다.
어느날 다해봐 연구원은 팀장님에게 과제를 받게 됩니다. 63개에 데이터를 보내는 시간을 단축하라는 과제 였습니다.
팀장님 : 다해봐 연구원, 잠깐 자리로 오시겠어요?
다해봐 연구원 : 네~
팀장님 : 지금 담당하는 기능이 데이터의 전송인데, 그 데이터를 보내는 속도를 좀 개선해 보세요.
다해봐 연구원 : 네...
다해봐 연구원은 고민에 빠지게 됩니다. 얼마나 개선을 해야 하는지? 지금이 문제인지?
소스 코드를 분석해 보니 우선 다음과 같은 구조였습니다.
int numberOfProcessors = 63;
while(numberOfProcessors > 0){
sendData(readsize, buffersize...);
}
대략의 내용을 보니, 전체 processor에 데이터를 보내는 기능을 하고, sendData가 이 역할을 하고 있었습니다. 그리고 sendData는 모든 data를 보내야지만 종료하도록 설계되어 있었습니다. 다시말해서 63개의 processor가 순차적으로 데이터를 받아가 고 있었던 것입니다. 그런데...
잠시만 생각해 보면, 다시 sendData는 HDD에서 data를 메모리로 읽어 들이고, 다시 메모리로 읽는 과정과 보내는 과정은 원본 데이터를 잘게 나누었다가 다시 조립하는 과정을 거치게 됩니다.
그래서 우선은 보내는 크기와 읽어 들이는 크기를 조정하기로 마음을 먹고, 우선은 readsize를 1KByte, 2KByte, 3KByte이렇게 늘려가면서 시험을 시작했습니다. 그런데 다해봐 연구원은...이런 의문에 빠져듭니다. 도대체 언제까지 해야 하지?
이렇게 고민하고 있는 다해봐 연구원을 다시 팀장님이 부르십니다.
팀장님 : 다해봐 연구원, 잘 진행되고 있나요?
다해봐연구원 : 아..네.. 이제 실험을 시작했는데 정확히 얼마나 해야 할지 잘 몰라서 고민이 됩니다.
팀장님 : 그래요, 일단 해보고, 참 그런데 지금 데이터를 보내는 것이 순차적이어서 시간이 많이 걸리는 것 같아요.
데이터를 여러개의 processor에 동시에 보낼 수 있도록 구조를 바꾸어 보세요.
다해봐연구원 : (헐)
고민끝에 다해봐연구원은 다음과 같이 구조를 변경합니다.
int numberOfProcessors = 63;
while(numberOfProcessors > 0){
startProcess(sendData(readsize, buffersize...));
}
사실 구조는 간단합니다. Android의 startservice나 linux의 fork와 같이 새로운 thread를 동시에 여러개 만들어서,
전송을 하도록 변경하였습니다. 조금만 생각해 보면, 동시에 여러개의 processor에 보내는 것이 큰 이득인 것을 알수 있습니다.
왜냐하면, 예를 들어 다음과 같은 그림에서 a process가 HDD에 접근할때, b는 놀게 됩니다. 따라서 a가 HDD에 접근할때, b가 다른 processor로 전송을 할 수 있다면, 여러개의 resource를 활용하는 활용도가 높아지게 됩니다. 따라서, 이렇게 하는 것이 좋을 것 같다는 생각을 했는데요....
생각보다 데이터를 모두 전송하는 시간이 그리 줄어들지가 않았습니다. 그리고 상황에 따라서는 더 늘어나는 현상도 발생을 하고, 무언가 예측하지 못한 일들이 벌어지기 시작했습니다.
자, 여기서 다시 팀장님이 등장하십니다.
팀장님 : 동시에 63개에 다 보내지 말고, 개수를 제한해보는 게 어떨까? 32개? 16개? 아니면 4개?
여기에서 의미가 있는 내용들을 추려 보겠습니다. 사실 software개발자들이 거의 매일마다 마주하는 문제들이고, 참 해결하기 어려운 문제입니다. 자신이 속한 시스템이나 대상이 다를뿐 정말로 까다로운 문제들입니다.
동시에 63개에 다 보내지 말고, 개수를 제한해 보는게 어떨까?
HDD에서 읽어들이는 파일의 최적화된 블록사이즈는?
통신장비를 통해서 보낼 packet의 최적 사이즈는?
위의 문제들이 어려운 것은, 특히 embed system에서 많이 발생하고, 더욱이 어려운 것은 탐색해야 하는 범위가 굉장히 넓다는 것입니다. 그리고 더 어려운 것은, 만약 위의 3가지 간에 상호작용이 있다면 최적의 크기를 찾는 것은 정말 어려운 문제가 됩니다.
이를 매우 효율적으로, 그리고 가능한 정확하게 찾아내는 방법론들이 six sigma의 방법론입니다. 거기에 더해서 한번 개선한 것들이 앞으로 쭈욱 잘 적용되고 있는지를 보는데에도 매우 좋은 방법입니다. 위의 3가지 질문에 대한 답은 마지막에 드리도록 하겠습니다.
1부 Software Sixsigma란?
0. Six sigma란?
간단하게 이야기하면 일을 잘하는 방법이고, 또한 "smarter than harder"로 정의할수 있습니다. 즉 six sigma는 일을 효율적으로 하는 방법입니다. 다시 말하면 효율적이지 않으면 six sigma가 아닙니다.
조금 더 나아가서 six sigma는 일을 효율적으로 하기위해 정형화된 framework을 제공합니다. DMAIC가 그것이고 DMADV처럼 발전된 형태가 있으나 가장 기본이 되는 것이 DMAIC입니다. 사실 software에서는 software architecture design이라는 좋은 방법이 있고, six sigma는 이의 개선 또는 software의 quality attribute를 측정하고 비교 개선하는 데 사용하기도 합니다.
실제로 어떻게 smarter than harder가 되는지를 사례를 통해서 보도록 하겠습니다.
sendPacketData(bufferSize, packetType)이란 2개의 parameter를 가진 method를 가정합시다. 그리고 buffersize는 4K, 16K, 의 2가지 크기와 packetType은 STREAM, CHAR의 2가지가 있습니다. 이 중에서 제일 성능이 잘 나오는 최적의 조합을 찾아야 한다면 어떻게 하는 것이 좋을까요?
일반적으로 접근을 해야 한다면 2가지의 bufferSize에 대해서 2가지 packetType의 조합을 모두 시험해 보아야 합니다. 반복을 하지 않는다면 모두 4번만 해보면 됩니다. 할만 합니다.
이후에 sendPacketData가 version up을 하면서 parameter가 2개 더 추가되었고, 각각은 다음과 같습니다.
이 경우에는 모두 16번을 하면 됩니다. 아직까지는 할만 합니다.
만약, 그 다음 version up에서 parameter가 4개 더 추가되고, 각각의 parameter가 2가지의 값을 가질수 있다면....모두 몇번을 확인해 보아야 할까요? 네, 2^8 = 256번 시험을 해보아야 합니다. 만약 한 번의 시험으로 원하는 결과를 얻기 힘들어서 2번씩 반복을 해야 한다면 512번 시험을 해야 합니다. 이 방법이 옳은지 모르겠지만, harder한 방법인 것은 맞는 것 같습니다. 한번 시험하는 데 10분씩 잡아도 5120분, 즉 85시간동안 시험을 하는 것입니다. 그것도 한번도 쉬지 않고 했을때의 이야기 입니다. 이는 다음과 같은 방법으로 빠르게 해결할 수 있습니다.
우선 8개의 parameter중에서 어떤 것이 성능에 영향을 더 많이 주는지 찾아 냅니다. 이 시험은 32번이면 충분합니다. 이렇게 해서 영향을 많이 주는 parameter가 3개 정도로 확인이 되면, 이 3개에 대해서 자세히 반복까지 포함하여 실험을 합니다. 그렇게 해도 16번이면 충분합니다. 이렇게 하면 전체 실험의 회수는 32 + 16 = 48번이고, 8시간이면 원하는 결과를 얻을 수 있습니다.
비교해보면 85시간과 8시간 중에 어떤 것이 smart한 방법일까요? 당연히 8시간이 훨씬 더 smart한 방법입니다.
위의 사례는 six sigma중에서도 실험계획과 분석에 대한 내용입니다.
다음부터는 software에 쓰이는 각 단계에서의 기술을 보도록 하겠습니다
1. Define
문제가 무엇인지 명확하게 설정하는 것이 define 단계입니다. 문제가 무엇인지, 그리고 명확하게 설정하는 것은 적어도 다음의 내용을 포함해야 합니다.
- 문제 자체에 대한 설명
- 문제의 배경, 왜 이것이 문제화 되었는지..
- 일반인들이 이해하는 내용인지, 혹은 이를 solution domain으로 전환한 내용인지
- 정확한 현상과 이에 따른 문제점을 분리해 냈는지..
그 밖에도 define단계에서는 전체적인 일정, 참여해야 하는 팀의 구성을 하게 되고, 필요하다면 팀 빌딩을 수행하게 됩니다.
다음과 같은 문제 정의를 보시겠습니다.
"연구소에는 지각하는 사람이 많다", 문제는 어느 정도 기술이 되었습니다. 연구소에서 일하는 연구원들중에서 정해진 출근 시간에 오지 않는 사람이 많은 것 같다는 것이 문제입니다. 하지만 위에서 이야기한 문제의 배경, 왜 문제인지, 일반적인 내용인지, 현상과 문제점이 분리되었는지를 생각해 보면 그렇지 않은 것 같습니다. 하나 하나씩 추가해 보도록 합시다.
"연구소에 지각하는 사람이 많다. 지각으로 인해 회의를 제 시각에 시작할 수 없어서, 업무의 효율성이 떨어진다."
조금 나아졌습니다. 생각해 보면 지각은 현상이고, 이로 인해 벌어지는 문제는 업무의 효율성입니다. 그 전에 지각하는 사람이 정말 많은지에 대해서도 생각해 보아야 합니다.
"연구소는 모두 2000명이고, 이 중에 1000명이 매일마다 지각을 한다. 이로 인해 회의를 제 시각에 시작할 수 없어서 문제이고, 이로 인해서 업무 효율성이 떨어진다." 로 이야기하면 조금 더 명확해 집니다.
이렇게 이해하기 쉬운 문제들만 있으면 좋겠지만, 예를 들어 다음과 같은 경우 숫자로 명확하게 제시를 해도 문제의 이해 자체가 어렵습니다. 이럴때에는 반드시 해당 문제점이 발생한 시스템 혹은 대상물에 대한 설명을 해주어야 합니다. 예를 들어, "Standby loading의 성능이 좋지 않다. 100번 시도하면 평균 2시간이상 걸리고, 이로 인해 고객의 불만이 증가하고 있다." 이 경우 아무리 말을 잘 풀어써도 "Standby loading"에 대한 설명을 하지 않으면 그 뒤의 내용을 이해할수가 없게 됩니다.
따라서 이에 대해서도 명확히 설명을 해 주어야 합니다. 그리고 이후에 변경이 되더라도 DMAIC를 언제부터 언제까지 할것인지, 그리고 각각이 단계에서 중요한 것은 무엇인지, 그리고 누가 앞으로 어떤 일을 할것인지에 대해서 기술을 해야 합니다.