Linear Congruential Generator를 병렬화하고싶습니다.
글쓴이: Samuro / 작성시간: 금, 2016/05/20 - 4:06오후
우선 이렇게생긴 코드입니다.
#define MODLUS 2147483647 #define MULT1 24112 #define MULT2 26143 long zi, lowprd, hi31; zi = zrng[stream]; lowprd = (zi & 65535) * MULT1; hi31 = (zi >> 16) * MULT1 + (lowprd >> 16); zi = ((lowprd & 65535) - MODLUS) + ((hi31 & 32767) << 16) + (hi31 >> 15); if (zi < 0) zi += MODLUS; lowprd = (zi & 65535) * MULT2; hi31 = (zi >> 16) * MULT2 + (lowprd >> 16); zi = ((lowprd & 65535) - MODLUS) + ((hi31 & 32767) << 16) + (hi31 >> 15); if (zi < 0) zi += MODLUS; zrng[stream] = zi; return (zi >> 7 | 1) / 16777216.0;
이 현재 만드는 프로그램에서 이LCG가 병목이어서 병렬화시키고 싶습니다. 숫자를 바꿀순 없고 저상태로 linear하게 실행했을때와 동일한 결과가 나와야 합니다.
합동식을 풀어서 병렬화 할수 있다고 하는데 도저히 모르겠네요 며칠째 이것만 보고있는데 수학이 약해서 그런지...
이 질문에 답변을 보면 x(n)= a*x(n-1)+c 형태일때 병렬화 하는 방법이 나와있는데 위의 코드에도 가능한 방법인가요? 이해한것 같은데도 저 LCG는 병렬화 못하겠네요.
어떻게해야 저 코드를 병렬화 할 수 있을지, 그러니까 x(999) 까지 구하지않고 x(1000)을 구하려면 어떻게 해야 하는지.. 제발 도와주세요 ㅠㅠㅠ
Forums:
1. http://www.cs.uml.edu/~gia
1.
http://www.cs.uml.edu/~giam/Mikkeli/Inventory/lcgrand.c
참고해서 아래 코드로 테스트해 보았는데, 동일한 결과가 나옵니다. 속도는 한 25% 정도 더 빠릅니다. 아마도 인용하신 코드는 64bit 곱셈이 없거나, mod 연산이 느린 환경에 대비한 코드가 아닌가 생각합니다.
이 코드를 활용하면, 링크하신 글의 방법론을 적용하기 쉬울 거 같습니다.
2.
http://www.drdobbs.com/tools/fast-high-quality-parallel-random-number/229625477
http://www.drdobbs.com/tools/fast-high-quality-parallel-random-number/231000484
이 곳에 소개된 랜덤함수 중 하나를 테스트해 보았는데, 속도는 약간 빠른 정도인데, 랜덤 특성이 좋다고 하니까 참고해도 될 거 같습니다.
3.
http://www.reedbeta.com/blog/2013/01/12/quick-and-easy-gpu-random-numbers-in-d3d11/
가만히 생각해 보면 "난수라는 특성 상",
CPU나 GPU의 멀티 코어를 활용해서 난수 수열을 생성하기 위해서는 그냥 seed값을 공유하지 않게 구현해서 코어별로 난수를 생성해서 합쳐도 될 거 같습니다.
예를 들어 2CPU를 활용해서 x[0] ~ x[999]를 얻기 위해서는 CPU0으로 x[0] ~ x[499]를 생성하고 CPU1에서는 x[500] ~ x[999]를 생성하는 식으로요.
메모리 접근에 병목만 없다면 이상적으로는 코어 수에 비례해서 이득을 볼 수 있겠죠.
그런데 랜덤 함수가 이상적이 아니기 때문에 또 seed값을 어떻게 만들었느냐에 따라서, 이렇게 생성된 수열의 랜덤 특성이 떨어지게 되는 거 같습니다. 위 링크를 살펴 보시면 그걸 보강하는 방법을 소개하고 있습니다.
지나가다 잘 배웠습니다. 질문을 보고 저런 함수를
지나가다 잘 배웠습니다.
질문을 보고 저런 함수를 어떻게 병렬화할까 싶어서 수식으로 만들어보다가 집어던졌는데
저렇게 간단히 정리가 되는군요. 다른 자료도 좋네요.
댓글 달기