ko zh ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko en ko ko ko en ko ko en ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ja ko ko ko ko ko ko en ko ko ko ko ko ko ko ko de ko de ko de ko ko ko ko ko ko ko ko en ko ko ko en ko en ko ko ko ko ko ko ko en ko ko ko ko ko ko ko ko ko ko de ko it ko en ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko ko uk ko ko ko ko ko ko ko ko en en ko ko ko ko ko ko ko ko ko ko ko ko ko ko en ko ko ko en en en en ko ko ko ko en ko ko ko ko ko ko ko ko ko ko de
Rust는 랜드 크레이트를 위해 더 나은 비 암호화 프로그램이 필요합니다. 이것은 내가 어떻게 하나를 디자인했는지에 대한 설명입니다. 결과 알고리즘이 고려할 가치가 있음을 보여줄뿐만 아니라 PRNG를 구축하려는 다른 사람들에게 가이드로 사용할 수 있기를 바랍니다.
원래 SmallRng는 PCG-32 및 PCG-64 였습니다. 약 1 년 전에 xoshiro128 ++ 및 xoshiro256 ++ 로 전환되었습니다 .
몇 가지 우려가 게시 xoshiro의 저자에 의해 제기 된 후에 수행 된 PCG에 블로그 항목을 또한 문제를 제기 PCG가 반전되는 가능성에. PCG의 저자의 답변은 읽을만한 가치가 있습니다.
나중에 Sorbonne의 일부 학생들은 그것을 뒤집는 방법을 찾았습니다 . (실제로 Rust의 PCG 구현을 사용하는 경우 암호화 보안이 필요하지 않은 경우 이는 문제가되지 않을 것입니다. Rust의 구현을 반전하고 상태를 얻으려면 2⁶²-2⁷⁰ 작업 사이에 걸립니다) 그러나 다음과 같은 일부 영역을 강조합니다. 개선 될 수 있습니다.
Xoshiro는 더 빠르고 더 높은 품질의 숫자를 생성 할 수 있었기 때문에 대체품으로 선택되었습니다. 현재 xoshiro256 ++에 대해 알려진 문제는 없습니다. 그러나 이것이 얼마나 오래 지속될지는 분명하지 않습니다. 생성기 제품군의 다른 구성원에는 몇 가지 알려진 문제가 있습니다.
아이러니하게도 xoroshiro128 + 및 xoroshiro256 +는 반전 속도가 훨씬 빠릅니다 . (일정한 시간에 할 수 있음) Xoshiro128 ** 및 256 **도 반전 될 수 있습니다 . 이것이 "++"변형으로 확장 될 수 있는지는 알 수 없습니다. ( 이것은 전환 당시에 알려 졌지만 언급되지 않았습니다 )
Xoroshiro128 +는 PractRand 테스트 스위트를 통과하지 못합니다 (128 비트 상태 임에도 불구하고 고품질 알고리즘은 절반으로 통과 할 수 있어야합니다). (출력을 잘라도 문제가 해결되지 않음)
Xorshift +는 또한 BigCrush 실패 하고 선형 문제가있다 . 더 큰 상태 라도 문제가 해결되지는 않습니다 .
xoshiro256 **도 크랙되었으며 출력에 57을 곱하면 통계적 문제가 발생하고 다른 잠재적 인 문제 가있을 수 있습니다 .
그렇다면 PCG에 어떤 문제가 있습니까?
PCG의 전체적인 디자인은 견고합니다. 그러나 몇 가지 실질적인 문제가 있습니다.
PCG는 곱셈을 기반으로합니다. 곱셈은 ​​훌륭한 믹싱 기능입니다. AND와 XOR 측면에서 곱셈이 어떻게 생겼는지 알아 내면 64 비트 곱셈이 얼마나 정교한 지 분명해집니다. 하드웨어에서 구현하는 데 필요한 트랜지스터의 양으로 인해 대부분의 암호화 알고리즘에서 곱셈이 사용되지 않습니다. 그러나 범용 CPU에서만 실행해야하는 비 암호화 PRNG의 경우 이미 하드웨어 구현이 있기 때문에 곱셈이 매우 유용합니다. 곱셈에는 한 가지 큰 단점이 있습니다. 하위 비트는 상위 비트에 영향을 미칠 수 있지만 그 반대는 아닙니다.
PCG에서 이것은 하위 비트의주기가 상위 비트보다 작다는 것을 의미합니다. 사실, LCG 의 N 번째 비트의주기 는 2ⁿ입니다. PCG-64의 경우 이는 128 비트 내부 상태의 하위 32 비트가 품질이 좋지 않음을 의미합니다. PCG의 출력 사전 돌연변이는 문제가되지 않도록 특별히 설계되었습니다.
으로 LCG (PCG에 기초한다) 증가는 홀수 일 수있다. 일부 구현에서 증분은 생성기의 전체 기간을 갖는 "독립적 인"시퀀스 인 "스트림"을 생성하기 위해 별도의 매개 변수로 사용됩니다. 이것은 종종 LCG에 관한 오래된 문헌에서 언급됩니다. 여러 스레드 각각에 대해 하나씩과 같은 여러 생성기를 만드는 방법으로 기능으로. 그러나 이것은 완전히 새로운 PRNG를 초기화하는 데 그다지 비싸지 않기 때문에 오늘날에는 그다지 의미가 없습니다. (이는 라이브러리에서 잘 처리되며 단일 시드는 암호화 된 강력한 prng를 사용하여 여러 개로 확장 될 수 있습니다.)
Rust rand 라이브러리는 증분을 단순히 시드의 일부로 취급합니다. 이것은“스트림”의 정확한 정의와 안전하게 어떤 가정을 할 수 있는지로 인한 혼동을 방지합니다. 또한 시드를 256 비트로 만듭니다. 이것은 무작위로 생성 된 많은 수의 생성기 가 생일 역설 로 인해 시퀀스에서 서로 가깝게 끝나지 않도록하기 때문에 유용합니다 . 단점은 상태가 128 비트에 불과하더라도 256 비트의 메모리를 사용한다는 것입니다.
다른 문제는 PCG-64가 다소 느리다는 것입니다. 업데이트에는 128 비트 곱하기가 필요합니다. 이것은 하드웨어 명령이 아닙니다. (적어도 내가 액세스 할 수있는 CPU에는 없음). 4 개의 64 비트 곱셈과 7 개의 더하기로 컴파일됩니다. 내 컴퓨터에서 PCG-64는 상태가 절반 크기이고 업데이트 기능이 더 간단하더라도 xoshiro256 ++보다 10-15 % 느립니다. (PCG-64-fast가 더 빠르지 만 여전히 가깝습니다.)
속도와 메모리 사용으로 인해 PCG-64 구현은 상태가 128 비트 만 있더라도 256 비트 생성기와 비교됩니다. PGC의 뛰어난 디자인은 무게를 뛰어 넘을 수 있지만 최고의 알고리즘조차도 상태 크기가 두 배인 괜찮은 알고리즘과 경쟁 할 수있는 방법은 없습니다. PRNG의 경우 상태 비트 수는 품질에 큰 영향을 미칠 수 있습니다. ( PGC 논문 은 상태 크기가 왜 그렇게 중요한지 설명하는 데 효과적입니다)
아직 읽지 않았다면 PGC 논문 은 난수 생성에 관한 최고의 논문 중 하나입니다. 읽을만한 가치가 있으며 매우 접근하기 쉽습니다.
이 논문은 PCG의 디자인을 강력하게 증명합니다. LCG의 상태 업데이트 기능을 출력 순열과 결합하면 정말 강력한 생성기가됩니다. (순열이 곱셈으로 통근하지 않는다고 가정)
알고리즘이 나쁘다는 것을 보여주는 것은 쉽지만 좋은 것을 보여주는 것은 훨씬 더 어렵 기 때문에 자신감을 심어주는 것은 쉬운 일이 아닙니다. PCG 페이퍼가이를 관리합니다.
문제는 무작위성 테스트가 그다지 좋지 않다는 것입니다. 그럴 수 없습니다. 애플리케이션은 생성 된 숫자를 어떤 테스트 스위트에서도 다룰 수없는 수백만 가지 방식으로 사용할 것입니다.
대신 PCG 논문은 통계적 결함을 감지하는 능력이 상태 크기의 함수임을 보여줍니다. 더 작은 상태로 작동하는 동일한 알고리즘의 "축소 된"버전을 만들면 문제를 훨씬 쉽게 감지 할 수 있습니다. 알고리즘이 작은 상태 크기로 강력하다면 더 큰 버전은 기하 급수적으로 더 커야합니다. (또는 그렇지 않으면 뭔가 잘못된 것입니다)
이 작업과 경쟁하려고하기보다, 저의 목표는이를 기반으로 PCG와 매우 가까운 사촌이지만 위에서 설명한 Rust 구현의 문제를 해결하는 생성기를 만드는 것입니다. 이러한 알고리즘의 목표는 다음과 같습니다.
256 비트 상태를 가지고 모두 활용하십시오.
A는 증명 가능한 기간이 있습니다. (테스트에서 발견되지 않은 동일한 5 개의 숫자를 반복 할 확률이 2⁴⁵ 중 1이 아니라는 것을 확인하고 싶습니다)
PCG와 유사한 구조로되어있어 동일한 기술을 사용하여 쉽게 분석하고 검증 할 수 있습니다.
보다 철저하게 테스트 할 수있는 더 작은 버전의 알고리즘으로 "축소"할 수 있습니다. (IE : 실패하기에는 너무 크지 않다는 것을 증명하십시오 )
128 비트가 아닌 64 비트 곱셈을 사용하여 업데이트 비용이 많이 들지 않습니다.
상위 비트가 하위 비트에 영향을 미칠 수 있는지 확인
여분의 비트가 많은 임의성에 대한 모든 표준 테스트 스위트를 통과하십시오.
PCG-64 및 xoshiro256 ++보다 훨씬 빠릅니다.
먼저 우리는 비트가 낭비되지 않는 256 비트 상태의 생성기를 만드는 방법을 원합니다. PCG-Fast는 MCG 생성기를 사용합니다 . 이것은 생성기의 크기를 상태 크기로 줄이는 증분을 제거합니다.
256 비트 LCG 또는 MCG 기반 생성기의 어려움은 256 비트 곱셈이 필요하므로 업데이트 기능을 비싸게 만듭니다.
상태를 확장 할 수있는 LCG의 대안이 있습니다 : MWC ( Carry Generator)를 사용한 곱하기 . MWC 생성기는 실제로 매우 특정한 MCG 생성기와 동일하므로 여전히 PCG 프레임 워크에 맞출 수 있어야합니다.
업데이트 기능이 64 비트 상태의 LCG와 동일한 비용 인 256 비트 상태를 가지도록 Lag-3 64 비트 MWC 생성기를 만들 수 있어야합니다. 출력에 대한 상태의 적절한 순열과 결합하여 빠른 고품질 생성기를 구축 할 수 있어야합니다.
64 비트 Lag-3 MWC 생성기에는 4 개의 64 비트 변수 인“ C ”,“ X1 ”,“ X2 ”,“ X3 ”이 있습니다. 여기서 X는 이전 3 라운드에 대한 계산 된 출력을 포함합니다. 업데이트 기능은 다음으로 구성됩니다.
T = a * X3 + C
어디 a는 상수이다. T 는 임시 변수입니다. 의 상위 64 비트 T가 할당되고 C 와 하부가 할당된다 X1 . 이전 값 후 X1이 저장된다 X2 및 X2 에서의 값 X3 .
여기서 무슨 일이 일어나고 있습니까?
이것은 실제로 특정 형식 의 256 비트 MGC ( Multiplicative Congruential Generator )와 동일합니다. 즉, 다음과 같습니다.
X = a * X mod a * 2¹⁹²-1
(여기서 X는 256 비트 값)
이 프로세스는 각 "숫자"가 2⁶⁴ 값을 가질 수있는 긴 곱셈과 유사합니다. 따라서 프로세스는 다음과 같습니다.
c X1 X2 X3 * a ________________ ac a*X1 a*X2 + a*X3 _________________
ㅁ 발생기의 진정한 천재는 곱셈을 필요로 할 때 발생하는 것입니다 C 에 의해 때문에, C는 이미 2¹⁹²s 장소에서 시작, 전체 작업이 모듈로 인 A * 2¹⁹²-1을 때 C는 에 의해 "곱셈"입니다 그 모듈러스 경계에서 정확히 감싸는 것이 보장됩니다. 따라서 곱셈을 수행하는 대신 c 를 1의 자리에 추가 할 수 있습니다.
즉, 3 개의 64 비트 곱셈과 3 개의 더하기를 통해 256 비트 값에 64 비트 값을 곱하여 다른 256 비트 값을 모듈로 할 수 있습니다. MWC의 업데이트 기능에 대한 세 번의 호출은 더 큰 MCG에 대한 한 번의 업데이트와 정확히 동일합니다. 또한 업데이트는 각 64 비트 섹션에 대한 비트를 곱하고 더한 후 점진적으로 계산됩니다. 64 비트의 출력 만 필요한 경우 출력 당 하나의 곱셈과 더하기 만 필요합니다. (추가적으로 포인터가 필요하지 않도록 X 를 재정렬 할 수 있습니다.)
MWC 생성기에 쉽게 적용 할 수 있도록 MCG에 적용되는 표준 분석 기술입니다. 증분을 저장할 필요가 없으며 모듈러스가 2의 거듭 제곱이 아니기 때문에 고차 비트는 결국 하위 비트에 영향을 미칩니다. 그러나 배수도 계수를 나타 내기 때문에 배수를 선택할 때 다소 엄격한 기준이 필요합니다.
난수 생성기를 연구하려면 생성기의 축소 된 버전의 "랜도 그램"을 살펴 봐야합니다. 랜도 그램은 배경이 흰색이고 각 픽셀에 X 및 Y 좌표가있는 이미지입니다. 첫 번째 숫자가 X 좌표를 형성하고 두 번째 숫자가 Y가되고 해당 픽셀이 어두워지면 난수가 생성됩니다.
예를 들어 아래는 8 비트 LCG의 출력입니다.
8 비트 LCG의 랜도 그램
각 출력은 1 바이트이며 각 쌍은 1 픽셀을 채색합니다. 위의 내용은 LCG의 전체 기간 동안 실행됩니다. 결과적으로 그 구조가 시각적으로 분명합니다.
"지연"을 추가하여 동일한 개념을 확장 할 수 있습니다. 인접한 숫자 쌍을 그리는 대신 그 사이에있는 일부 값을 건너 뛸 수 있습니다.
다음은 0-8 값을 건너 뛰는 동일한 8 비트 LCG입니다. (왼쪽에서 오른쪽으로)
8 비트 LCG 랜도 그램
지연을 변경하면 패턴이 다르게 나타나지만 구조는 여전히 분명합니다.
PCG는 LCG 위에 스크램블링 기능을 추가하여 구조를 찾기 어렵게 만듭니다. 8 비트 상태로 축소했을 때의 모습은 다음과 같습니다.
8 비트 LCG-XLS-RR 랜도 그램
이것은 훨씬 더 좋아 보인다! 그것들은 분명히 훨씬 더 무작위로 보입니다. 여전히 숨겨진 구조가 있다는 사실은 명백한 어둡거나 밝음이 지연에 따라 달라진다는 사실에 의해 분명해집니다. 이것은 정확한 충돌의 다른 비율에 해당합니다.
대신 8 비트 Lag-3 MWC 생성기의 스펙트럼을 플로팅하면 다음과 같은 결과를 얻을 수 있습니다.
8 비트 지연 -3 MWC 랜도 그램
세 번째 섹션을 제외하고는 모두 놀랍습니다. 두 개의 숫자를 건너 뛰는 경우에 해당합니다. 위의 LCG 스펙트럼과 매우 비슷해 보이면 그것이 바로 그 때문입니다.
MWC의 업데이트 기능이 동일한 X에서 다시 작동하는 경우에 해당하는 두 개의 숫자를 건너 뛰는 경우. 그래서 그것은 단지 수행하고 있습니다 :
X = a * X + c 모드 2⁶⁴
같은 세포에서. 이것은 LCG와 똑같은 공식이므로 물론 비슷하게 보일 것입니다.
실제로 한 단계 더 나아가면 연속 출력을 쌍으로 만들어 8 비트 생성기를 16 비트 생성기로 바꾸고 65536 x 65536 버전의 스펙트럼을 그래프로 표시합니다. (이 작업을 수행했지만 명백한 이유로 여기에 업로드하지 않았습니다.) LCG 또는 MCG 스펙트럼처럼 보입니다. 이것은 예상됩니다. 결국 MWC는 하드웨어 크기가 곱해지는 것보다 훨씬 더 큰 MCG로 작업 할 수 있도록하는 영리한 트릭입니다.
출력에 패턴이 생기지 않도록하려면이를 마스킹 할 출력 순열을 찾아야합니다. 패턴을 마스킹하기 전에 패턴이 존재 하는 이유 를 이해 하는 것이 중요 합니다. 이 경우 LCG의 패턴이라는 것을 알기 때문에 PCG가 LCG에서 패턴을 마스킹하는 데 사용하는 것과 동일한 기술을 사용할 수 있습니다.
다행히 PGC 문서 는이를 수행하는 방법에 대한 일련의 지침을 제공합니다. 두 가지 핵심 아이디어가 있습니다. 첫째, 함수는 순열 (즉, 가역적)이어야 출력이 입력보다 더 나 빠지지 않도록합니다. 둘째, 통근하지 않는 사업자를 이용하여 비선형 성을 도입해야한다. (IE : 업데이트 함수가 곱셈 인 경우 출력 함수도 곱셈이되어서는 안됩니다.) 확률이 높을수록 결과가 더 무작위 적입니다.
우리는 할 수 있습니다 : 덧셈, XOR, XorShifts, Random Rotations, 그리고 사이에 xor가 있으면 두 번째 곱셈까지. 그리고 각 라운드 X1–3, C, 곱셈 후의 상위 비트 및 하위 비트에서 6 개의 가능한 숫자가 있습니다.
이러한 조합을 테스트 한 결과 X1 ^ X3 과 같은 매우 기본적인 변환조차도 LCG 패턴의 희미한 흔적 만 남겼습니다. (자세히 보면 알 수 있습니다)
X1 ^ X3 출력 순열이있는 8 비트 지연 -3 MCG
(이를 전체 65k * 65k 이미지 크기로 확대하면 패턴을 더 잘 볼 수 있습니다.) 두 개의 서로 다른 승수를 사용하고 출력 비트를 반전하지 않고 (조합 당 32 개 이미지) 8 개의 지연 시간 각각에서 65k * 65k 이미지를 구성하여 100 개가 넘는 연산 및 매개 변수 조합을 실험했습니다. 그런 다음 패턴을 시각적으로 식별 할 수없는 모든 조합에 대해 동등한 64 비트 버전의 알고리즘을 코딩하고 벤치마킹했습니다. 나는 결국 :
(X3 ^ X2) + (X1 ^ HI)
( HI 는 X3 * a의 상위 비트입니다 . 즉 , 추가에서 캐리가 없으면 다음 c 가 될 것입니다. ) 다음은 다음과 같습니다.
(X3 ^ X2) + (X1 ^ HI) 출력 기능이있는 8 비트 Lag-3 MCG
다음은 출력을 페어링하고 전체 기간을 실행 한 결과 65k * 65k 이미지 중 하나에서 각각 4 개의 512x512 슬라이스입니다. 이는 왼쪽에서 오른쪽으로 0에서 3까지의 지연에 해당합니다.
(X3 ^ X2) + (X1 ^ HI)가있는 8 비트 Lag-3 MCG (출력이 0–3 시차가있는 16 비트 정수로 쌍을 이룹니다)
이것은 정말 좋아 보이며 이론적 관점에서 Xs 에서 수행 된 마지막 작업 이 add 였으므로 이해할 수 있으므로 결국 add, xor, add의 순서로 끝납니다. 이것은 강력한 비선형 성을 제공하고 국가의 먼 관련 부분을 결합합니다.
PCG의 명명 규칙에 따라 이는 전체 크기 알고리즘이 다음과 같이 명명됨을 의미합니다.
이는 "64 비트 출력을 얻기 위해 XOR, XOR 및 Add (순서대로)로 순열 된 256 비트 상태의 MultiplyWithCarry"의 약자입니다. 마찬가지로 소형 버전의 이름은 Mwc-32-XXA-8입니다.
비교는 어떻습니까? 우리는 이미 PCG가 어떻게 생겼는지 보았습니다. 다음은 32 비트 상태로 축소 된 xoshiro256 ++ 버전에 해당하는 4 개의 라디오 그램 입니다. 일명 xoshiro 32 ++
8 비트 xoshiro32 ++ (출력이 0–3 시차가있는 16 비트 정수로 쌍을 이룹니다)
상황은 PCG와 유사합니다. 명백한 패턴은 없지만 다른 시차에서의 밀도 차이는 발전기의 기본 구조를 암시합니다. 이것은 놀랍거나 반드시 문제가되지는 않습니다. 전체 기간 동안 실행될 때 발전기에 대해 합리적으로 예상 할 수 있습니다.
그러나 이는이 방법이 lcg-xls-rr 및 xoshiro ++보다 더 높은 품질의 번호를 생성 할 수 있다는 것을 의미합니다. 테스트 만 알 수 있습니다. 그러나 그렇게하기 전에 먼저 배수를 선택해야합니다.
몇 가지 요구 사항이 있기 때문에 올바른 배수를 찾는 것은 까다 롭습니다. 먼저 최대 기간이 있어야합니다.
일반 MCG에서는 계수에 대해 최대 기간을 달성하기 위해 계수에 코 프라임이 필요합니다. 그래서 만약:
a * 2¹⁹² − 1
프라임이면 최대 기간이됩니다. 그러나 우리는 또한 mod 64 출력이 최대 기간이되기를 원합니다. 다음과 같은 경우에 해당됩니다.
a * 2¹⁹¹ − 1
또한 프라임입니다. 그러면 기간은 다음과 같습니다.
a * 2¹⁹¹ − 1
즉, a 가 크면 (2⁶⁴에 가까움) 256 비트 상태가 2²⁵⁶ 인 생성기의 이론적 최대 기간에 상당히 근접 할 수 있습니다.
지금까지 a에 대한 요구 사항은 다음 과 같습니다.
a * 2¹⁹² − 1은 소수입니다.
a * 2¹⁹¹ − 1은 소수입니다.
스펙트럼 테스트는 위에서 시각적으로 랜도 그램으로 수행 한 것과 유사하게 작동합니다. 전체 기간 동안 LCG를 실행하면 LCG의 기본 구조가 생성되는 것을 알고리즘 적으로 조사합니다. LCG는 항상 구조를 갖지만 구조가 더 균일하고 출력에서 ​​독특한 패턴을 생성하는 명확한 숫자 '밴드'를 생성하지 않는 것이 더 좋습니다.
스크램블링 기능이 구조의 효과를 극적으로 감소시키기 때문에 이것은 순열 된 출력에서는 문제가되지 않습니다. 그리고 256 비트 PRNG는 전체 기간에 가까운 곳에서 실행되지 않습니다. 그러나 선택이 주어지면 출력 순열 전에 잘 작동하는 배수를 선택하는 것이 좋습니다.
MCG에 대한 좋은 스펙트럼을 검색하는 코드를 다음과 같은 형식으로 설정했습니다.
X = a * X mod a * 2¹⁹²-1
문제가 있다는 것을 금방 깨달았습니다. 경우 A는 거의 2⁶⁴이며, 그 다음 좋은 64 비트를 여러 모듈을 2²⁵⁶ 찾기 위해 시도된다. 이것은 단순히 불가능합니다. 이유를 이해하려면 X가 너무 동일 하나에게 일어난 것을 우리 randogram에 상상, 다음 값이 될 것이다 . X가 2이면 2a 가 될 것입니다. 정의상 2⁶⁴보다 작은 a에 의해 분명히 다릅니다 . 이것은 2²⁵⁶의 아주 작은 부분입니다. 이것이 균일 분포에 접근 할 수있는 방법은 없습니다. 그렇게하려면 A는 계수의 비트 더 적은 수의 절반 이상이 번호를 가지고해야합니다.
그게 다야? 지연이 1보다 큰 모든 MWC가 불량입니까?
좀 빠지는. 우리는 실제로 다음에 관심이 없습니다.
X = a * X mod a * 2¹⁹²-1
X = a * X mod a * 2¹⁹²-1 mod 2⁶⁴
동일한 MCG의 전체 수가 아니라 개별 64 비트 구성 요소에만 관심이 있기 때문입니다.
X가 작은 경우 (<2¹⁹²) 다음과 같습니다.
X = a * X 모드 모드 2⁶⁴
그래서 우리의 스펙트럼 평가해야 을 가 일반 64 비트 MCG에 대한처럼. 이것이 작동 하려면 a 가 3 또는 5 mod 8과 일치해야합니다.
곱셈이 a * 2¹⁹²-1 모듈러스 경계를 감싸는 시기에 대한 질문도 있습니다 . 이를 방지하려면 다음의 스펙트럼도 테스트해야합니다.
X = a² * X 모드 a * 2¹⁹²-1
X = a³ * X mod a * 2¹⁹²-1
이제 a에 대한 요구 사항은 다음 과 같습니다.
a * 2¹⁹² − 1은 소수입니다.
a * 2¹⁹¹ − 1은 소수입니다.
모드 8 = 3 또는 5
X = a * X mod mod 2⁶⁴의 스펙트럼이 양호 함
X = a² * X mod a * 2¹⁹²-1은 양호한 스펙트럼을 가짐
X = a³ * X mod a * 2¹⁹²-1은 양호한 스펙트럼을 가짐
X = a⁵ * X mod a * 2¹⁹²-1은 좋은 스펙트럼을 가짐
이것은 2²⁵⁴ 이상의주기를 제공하고 우수한 스펙트럼 특성을 가지고 있습니다. 더 많은 CPU 시간으로 더 나은 값을 찾을 수 있지만 의미있는 차이를 만드는 것은 확실하지 않습니다.
품질 평가에 깊이 들어가기 전에 이것이 실제로 가치가 있는지 확인하는 것이 좋습니다. 순열 Mwc가 실제로 더 빠릅니까? 약간의 최적화 후 내 랩톱에서 1kb 바이트 배열을 채우는 데 대한 벤치 마크가 있습니다.
Mwc-256-X-X-A-64 (This algorithm): 100.98 ns Lcg-128-Xsh-RR-64 (Pcg64): 284.89 ns Mcg-128-Xsl-RR-64 (Pcg64-fast): 235.54 ns xoshiro256++: 233.41 ns
궁극적으로 모든 것은 품질로 귀결됩니다. 실제로 좋은 결과를 얻고 있는지 어떻게 확인할 수 있습니까?
난수 생성기에 대한 세 가지 주요 테스트 스위트가 있습니다.
DieHarder — 이것은 가장 간단한 테스트 스위트이며 통과하기 가장 쉽습니다. (단지 패키지를 설치하고 무작위로 파이프 :`dieharder -a -k 2 -Y 1 -g 200`)
TestU01 — 여기에는 많은 테스트가 포함되지만 C로 PRNG를 작성하고 정적 메모리에서 상태를 수정하여 작동하는 함수 포인터를 전달해야하기 때문에 사용하기가 매우 어렵습니다. 또한 PractRand 및 DieHarder만큼 P 값을 거의 처리하지 않습니다. 그러나 스위트 BigCrush가 표준이므로 매우 중요한 벤치 마크입니다.
PractRand — 처리하기 가장 쉽고 "효율성"측정에 편리합니다.
하지만 그것만으로는 충분하지 않습니다. 대신 테스트는 "축소 된"버전 Mwc-32-XXA-8에서 실행 되어 상태가 너무 커서 우연히 통과하지 않는지 확인 합니다.
또한이 테스트 스위트를 이진 통과 / 실패로 보는 것보다 더 나은 질문은 통과하는 데 필요한 상태 비트 수입니다.
예를 들어 BigCrush에는 2³⁵ 이상의 기간이 통과해야하는 테스트가 있습니다. 따라서 상태가 36 비트 미만인 PRNG는 테스트가 종료되기 전에 출력이 순환되어야하므로 정의에 따라 실패합니다. 실제로 생일 분포 로 인해 이론상 한계의 몇 비트 내에 만 있으면 아주 좋은 PRNG조차도 실패합니다 .
우리는 생성기의“효율성”을 통계 테스트를 통과하는 데 필요한 비트 수와 가능한 이론적 최소값의 비율로 정의 할 수 있습니다.
PractRand의 출력은 테스트를 계속 실행하고 결과적으로 테스트가 실패 할 때까지 읽은 임의 값 크기의 2의 거듭 제곱을 넘을 때마다 상태 업데이트를 출력하기 때문에이를 측정하는 데 매우 편리합니다. 유한 상태의 모든 생성기는 무한한 시간 프레임이 주어지면 실패합니다. 그러나 그들이 좋은 경우 실패하는 데 걸리는 시간은 상태 크기에 따라 기하 급수적으로 증가해야합니다. 실제적인 이유로 기본 컷오프는 32TB입니다.
다음 그래픽을 고려하십시오 ( pcg-random.org 블로그 "최소 표준을 능가합니까" 에서 노골적으로 도용 됨 ).
LCG 및 MCG의 측정 효율성 플롯 (출처)
이를 기반으로 LCG 및 MCG의 PractRand 테스트 스위트에서 효율성을 각각 58 % 및 56 % 로 정의 할 수 있습니다 . 이는 해당 비트 비율로 이론적으로 이상적인 생성기만큼 우수하기 때문입니다.
비교를 위해 다른 접근 방식 :
위에서부터 PCG의 축소 된 버전 인 Lcg-32-Xsh-RR-16 (PCG-16이라고도 함)은 2²⁸ 의 실패 지점을 가지고 있어 87 % 의 효율성을 제공합니다 .
위에서부터 xoshiro의 축소 된 버전 인 xoshiro32 ++는 2²⁸ 의 실패 지점을 가지고 있어 87 % 의 효율성을 제공합니다 .
위의 8 비트 lag-3 버전 인 Mwc-32-XXA-8은 PractRand 테스트 세트에서 2²⁸ 의 실패 지점이있어 87 % 의 효율성을 제공합니다.
참고 : 소형 MWC를 테스트 할 때 사용 된 승수 는 스펙트럼을 기반으로 선택 되지 않았으며 LCG 또는 MCG에 대해 잘못된 선택으로 간주됩니다. 이것은 알고리즘이 최적이 아닌 배수에서도 작동하는지 확인하기위한 것입니다.
두 번째 테스트로 다른 축소 버전을 만들었습니다. 지연 시간이 2 (총 48 비트)이고 출력 순열이있는 16 비트 MWC입니다.
(X2 ^ X1) + (C ^ HI);
X3 가 없기 때문에 다른 출력 순열이 필요합니다 . 이를 Mwc-48-XXA-16이라고 합니다.
PractRand 테스트 스위트에서 Mwc-48-XXA-16의 실패 지점은 2⁴³입니다. 이것은 알고리즘에 89 % 의 효율성을 제공합니다 . 이는 크기가 증가함에 따라 효율성이 일정하게 유지됨을 의미합니다. MCG가 순열 MWC를 뒷받침하는 것이 사실이라는 점을 감안할 때 이것은 놀라운 일이 아닙니다.
스케일 불변 효율은 매우 중요한 속성입니다. 왜냐하면 알고리즘이 스케일 업함에 따라 효율성이 감소하면 비트를 추가해도 품질이 향상되지 않는 특정 지점에서 한도에 도달 할 수있는 설계 결함을 나타 내기 때문입니다. (비선형 단계가없는 LFSR 등)
32 비트 버전 (Mwc-32-XXA-8)은 DieHarder 및 SmallCrush를 통과합니다. 거의 32 비트 생성기가 DieHarder를 통과 할 수 있고 SmallCrush를 통과 할 수있는 경우가 적기 때문에 이것은 중요합니다. BigCrush를 통과하지 않습니다. (그러나 이론적 인 최소 비트 수보다 적기 때문에 불가능합니다.)
48 비트 버전 (Mwc-48-XXA-16)은 전체 DieHarder, Crush 및 BigCrush 테스트 스위트를 통과합니다. 이는 BigCrush 테스트 스위트의 경우 알고리즘의 효율성이 75 % 이상 임을 의미합니다 .
Lag-4 생성기를 사용하여 알고리즘의 40 비트 버전을 테스트하고 싶었습니다. 그러나 a * 2⁴⁰-1 과 a * 2³⁹-1 이 모두 소수 인 8 비트 값이 없으므로이 크기의 전체주기 생성기를 구축 할 수 없습니다. 나는 227 의 배수로 하나를 테스트했습니다 . 이것은 최대 기간을 제공하지는 않지만 실험적으로 기간을 2³⁵의 수줍음 (~ 95 %) 인 32498585873으로 측정했습니다. (만약 기간 생성기가 존재했다면 2³⁹에 가까운 기간을 가졌을 것입니다.)
놀랍게도이 생성기는 BigCrush를 통과합니다! 이것은 테스트 스위트를 통과하는 가장 짧은 기간 생성기입니다! (이 기간은 실제로 통계적 문제가 감지되기 ​​시작해야하는 크기보다 작지만 테스트가 실제로 실패하게 만드는 데는 아직 멀지 않습니다.)
감소 된주기 40 비트 생성기는 가상의 전체주기 37 비트 생성기와 다소 유사합니다. 이러한 생성기는 유사한주기를 갖기 때문입니다. 따라서 BigCrush에서 순열 된 MWC 의 효율성은 97 % 입니다. 이 효율성은 PCG의 가장 강력하고 느린 멤버 인 PCG-RXS-M-XS에 의해서만 능가합니다. PCG는 현재 BigCrush를 통과 할 상태 비트가 가장 적은 생성기에 대한 기록을 보유하고 있습니다.
Number of bits needed to pass BigCrush: XorShift >100 LCG 88 PCG-XSH-RS 49 PCG-XSL-RR 48 XorShift* 40 PCG-XSH-RR 39 PCG-RXS-M-XS 36
Number of Crush + BigCrush failures at 32 bits. PCG-XSH-RS >100 PCG-XSH-RR >100 PCG-XSL-RR >100 XorShift* 57 xoshiro32++ 43 Mwc-32-X-X-A-8 40 PCG-RXS-M-XS 16
이러한 효율성은 상당히 좋습니다. 응용 프로그램이 PractRand만큼 트루 랜덤 편차에 민감하다고 가정합니다. Mwc-256-XXA-64를 사용하여 2⁶⁴ 생성기를 인스턴스화하는 애플리케이션은 각각 2⁶⁴ 출력을 생성하는 100 비트의 "헤드 룸"을 갖습니다. 이것은 실제 무작위에서 감지 가능한 편차가 발생하지 않을 것이라는 확신을줍니다.
분명히이 특정 알고리즘은 모든 PRNG를 끝내는 것이 아닙니다. 여기에 적절한 지 결정하는 데 도움이 될 수있는 몇 가지 장단점이 있습니다.
MWC는 곱셈에 크게 의존합니다. CPU에서 실행하는 경우 좋습니다. 그러나 GPU, FPGA, 마이크로 컨트롤러 또는 실리콘으로 구현하는 경우 더 나은 대안이 있습니다.
64 비트 곱하기 simd 명령어가 없으므로 성능은 대부분의 다른 알고리즘보다 우수하지만 하드웨어 특정 명령어를 활용하는 다른 더 빠른 알고리즘이있을 것입니다. 한 가지 흥미로운 기술은 aes-ni 명령어를 사용하는 것입니다. Randen 은 이것을하고 매우 빠릅니다. 축소 된 라운드 버전이 더 빠를 수 있습니다.
출력은 k 차원 등분 포를 제공하지 않습니다. 대부분의 응용 프로그램에서 이것은 단순히 관련이 없습니다. 예를 들어 PCG로 수행 할 수 있지만 Rust 버전은이를 구현하는 데 전혀 신경 쓰지 않았습니다. (또는 다른 생성기에서 지원). 이것이 존재하는 주된 이유는 도박과 같은 분야의 법적 요건에서 비롯된 것이라고 생각합니다. 2²⁵⁶에서 특정 출력 순서에 대한 편견이 실제적인 것이 없더라도 법적 결과를 초래하는 경우입니다.
길이 및 크기 유연성은 다른 아키텍처에 적합합니다. 예를 들어 32 비트 아키텍처에 대해 32 비트 곱셈을 사용하는 192 비트 버전이 가능합니다.
Lag를 증가시켜 상태의 크기를 확장하고 기간을 늘릴 수 있습니다. 그러나 그렇게하려면 새로운 배수를 검색해야합니다.
단어의 암호 학적 의미에서 PRNG는 이미 "파손"되었습니다. 출력은 3 개의 64 비트 값을 결합합니다. 그중 두 가지를 알고 출력을 관찰하면 세 번째가 드러납니다. 다음 반복을 관찰하면 전체 상태가 표시됩니다. 따라서 상태가 256 비트 인 경우에도 두 값을 무차별 대입하여 추측하여 2¹²⁸ 연산에 무엇이 있는지 알아낼 수 있어야합니다. 이것은 비 암호화 사용에 문제가되지 않습니다.
256 비트가 올바른 크기입니까? 192는 더 작을 것입니다. 320은 더 빠른 순열 함수를 허용 할 수 있으므로 CPU와 메모리를 교환 할 수 있습니다.
성능을 더욱 향상시킬 수 있습니까? 예를 들어 각 라운드에는 4 개의로드와 4 개의 메모리 저장이 포함됩니다. 그것들을 결합하는 것이 가능할 수 있습니다.
더 큰 크기의 곱셈으로 얼마나 얻습니까? 예를 들어 더 작은 배수로 더 큰 지연을 갖는 것이 훨씬 더 나쁠까요? 더 빠를 수 있습니까?
모든 코드를 github repo에 체크인 하고 github repo 에 대한 토론을 활성화했습니다. 질문이나 설명 은 거기에 게시 할 수 있습니다 .
읽을 가치가있는 관련 링크 :
PCG 종이 — https://www.pcg-random.org/pdf/hmc-cs-2014-0905.pdf
PRNG 개발에 대한 유사한 스타일 게시물 — http://burtleburtle.net/bob/rand/talksmall.html
ME O'neil의 블로그 — https://www.pcg-random.org/blog/
Lemire의 블로그 — https://lemire.me/blog
John Cook의 블로그 — https://www.johndcook.com/blog/tag/rng/
Peter O.의 github — https://peteroupc.github.io/
MWC 위키 백과 — https://en.wikipedia.org/wiki/Multiply-with-carry_pseudorandom_number_generator
DevX 이니셔티브 후원 프로그램: 목표 및 원칙
Concordium의 DevX Initiative는 Rust 생태계의 유지 관리자를 지원해야 한다고 믿습니다. Concordium은 Rust 생태계의 유지 관리자의 작업에서 이익을 얻는 상용 오픈 소스 프로젝트로서 Rust를 유지하는 작업에 기여해야 한다는 것을 알고 있습니다.
Rust의 제로 비용 추상화
안녕하세요, 이 포스트에서 우리는 Rust의 제로 비용 추상화에 대해 이야기할 것입니다. 이 게시물의 비디오 버전도 사용할 수 있습니다.
Epsilon-Delta를 사용하여 수학에서 추상적 사고 구축
눈을 감고 시간을 거슬러 올라가면, 교수가 칠판 옆에 서서 분필로 수학적 정의를 쓰는 동안 뒷줄에 앉아 슬퍼하는 대학생을 봅니다. 클릭, 클릭, 클릭 소리는 교수가 칠판에 글을 쓸 때마다 여전히 분명했습니다.
두 정수를 곱하기위한 Karatsuba 알고리즘
곱셈을위한 분할 및 정복 접근법
우리 모두는 어렸을 때 두 숫자를 곱하는 방법을 배웠습니다. (😄)를 잊은 경우에는 두 숫자 19와 95를 곱하는 방법을 살펴 보겠습니다.
수학 방정식 및 연산 시각화
수학 그래프를 사용하여 방정식의 본질을 포착하고 시각적으로 풀기
방정식의 본질에 대한 시각적 인 조사를 시작하기 전에 방정식은 관계이며 그 관계는 여러 가지 방법으로 기록 될 수 있음을 기억해야합니다. 이 기사 전체에서, 이것은 완전히 새로운 (적어도 나에게는) 사고 방식이기 때문에 오래 전에 배운 오래된 관습을 잊어 버리는 것이 중요합니다.
허구로서의 수학 : 상식적인 접근
다음 에세이는 제가 플로리다 대학교에서 학부생이었을 때 2014 년에 작성되었습니다. 그것은 수학의 역사 및 / 또는 철학에 대한 저술로 수학과의 Robert Long Prize를 수상했습니다. 그 사이에 수학적 대상의 존재 론적 / 주상 론적 상태에 대한 나의 견해는 다소 진화했습니다.