는 일상적인 연산이 여러 특성에 흩어져 있어, 더 작은 공개·구현 표면과 일관된 사용 경험을 갖춘 urandom을 개발함
구조체에 모으고 Rng
특성을 봉인해, 임의 생성기 지원보다 API 발견성과 내부 최적화를 우선함
- 새로운 난수 알고리듬을 도입하지 않고 Xoshiro256의 출력 함수를 용도별로 선택해, 1,000개
f64
생성 벤치마크에서 rand
0.10.2보다 약 31% 높은 처리량을 기록함
- 균등 정수 표본 추출은 임계값을 지연 계산하는 하나의
비편향 구현으로 재사용·일회성 경로를 통합했으며, 500..20_000
범위 벤치마크에서 rand
의 두 경로보다 빨랐음
- 명시적 시드의 원시 출력은 지원 아키텍처와 SemVer 호환 릴리스에서 재현성을 보장하지만,
임의 생성기 연결과 rand
의 방대한 분포·서드파티 통합 생태계는 포기함
하나로 모은 Random
API
rand
의 유용한 연산은 여러 특성에 흩어져 있음
, 시퀀스 선택에는 IndexedRandom
, 섞기에는 SliceRandom
이 필요함
rand
0.10은 일회성 호출을 위한 rand::random_range
같은 루트 수준 도우미를 제공함
-
RNG 핸들을 유지하거나 선택·섞기 같은 시퀀스 연산을 사용하려면 여전히 여러 특성의 메서드를 찾아야 함
-
prelude로 가져오기를 줄여도 확장 메서드가 RNG, 슬라이스, 반복자 중 어느 타입에 적용되는지 알아야 하므로 IDE 자동 완성만으로 찾기 어려움
-
urandom은 고수준 소비자 API를 하나의
Random
래퍼 구조체에 배치함
urandom::new()
로 Random<urandom::rng::Xoshiro256Rng>
를 생성함
uniform
, choose
, shuffle
을 같은 객체에서 호출할 수 있음
, uniform
, chance
, choose
, shuffle
, sample
등을 확인할 수 있음
- 모두 고유 메서드이므로 고수준 확장 특성을 찾거나 가져올 필요가 없음
확장성 대신 최적화를 택한 봉인된 Rng
rand
는 저수준 RNG 특성을 공개 확장 지점으로 취급하지만, urandom
의 Rng
특성은 봉인되어 지원 생성기를 크레이트 내부에서 선택하고 구현함
에 연결할 수 없음
자체를 변경해야 함
-
더 나은 알고리듬이 목적이라면 현재 역할별 기본 선택으로 Xoshiro256과 ChaCha가 이미 자리 잡고 있으며, 권장 사항도 천천히 바뀜
-
더 나은 선택지가 생기면 향후 메이저 릴리스에서 채택할 수 있음
-
다른 프로젝트·프로그래밍 언어·레거시 알고리듬·특수 하드웨어·시뮬레이션 전용 생성기와 호환하려면 생성기만 같아서는 부족함
-
균등 표본 추출과 섞기 등 관련 알고리듬까지 같아야 하므로 전체 계약을 구현한 전용 구현이 더 적합함
-
봉인된 특성 덕분에 알 수 없는 생성기와 예외 상황을 위한 구현 계약을 설계·문서화하지 않고
urandom
에 필요한 원시 연산만 추가할 수 있음
- 생성기와 알고리듬을 서로 맞춰 특수화할 수 있어
rand
에서는 사용할 수 없는 일부 최적화가 가능함
- 대부분의 애플리케이션에서는 새 PRNG 구현보다
엔트로피 선택이 더 유용함
- 구체적인 생성기는 네이티브
from_seed
생성자를 공개함
ChaCha12Rng::from_seed(seed)
처럼 명시적 시드를 사용한 Random
을 만들 수 있음
- 임의 RNG 구현은 받지 않지만 고급 사용자가 필요로 할 것으로 예상되는 확장 지점은 유지함
같은 알고리듬에서 얻은 성능 향상
urandom
은 새로운 난수 생성 알고리듬을 사용하지 않음
- 64비트 시스템에서 비암호학적 용도의
urandom::new()
와 rand::rngs::SmallRng
은 같은 Xoshiro256 계열을 사용함
- 암호학적 용도의
urandom::csprng()
와 rand::rngs::StdRng
은 ChaCha12를 사용함
의 내부 생성기도 ChaCha12임
rand
의 생성기 인터페이스는 정수 워드와 바이트 채우기를 제공하므로 f64
가 필요한 분포도 전체 u64
부터 요청함
urandom::Rng
은 next_u32
, next_u64
뿐 아니라 next_f32
와 next_f64
도 제공함
-
부동소수점 난수는 전체 워드보다 적은 난수 비트가 필요함
-
생성기는 이 메서드들을 더 저렴한 출력 함수로 재정의할 수 있음
-
Xoshiro 구현은 상태 전이를 공유하면서 출력 경로를 구분함
u64
에는 Xoshiro256++를 유지함
u32
와 부동소수점에는 상위 비트가 해당 용도에 맞게 설계된 더 빠른 Xoshiro256+를 사용함
urandom
1.0과 rand
0.10.2로 각각 1,000개의 난수를 생성한 마이크로벤치마크 결과는 다음과 같음
: 양쪽 모두 814ns
: rand
836ns, urandom
788ns
: rand
1,033ns, urandom
788ns
: rand
2,199ns, urandom
2,011ns
의 종단 간 처리량은 약 31% 높고 실행 시간은 24% 짧았지만, 동일한 작업을 수행하는 u64
경로는 사실상 동률이었음
를 재정의하지 않아 성능이 대체로 비슷함
- 정확한 시간은 머신과 컴파일러에 따라 달라지며, 자세한 조건은 전체 벤치마크 노트에서 확인할 수 있음
하나로 통합한 균등 표본 추출 경로
- 정수를 범위 길이로 단순 나머지 연산하면
편향이 생기므로, 올바른 균등 정수 표본 추출은 생성기 출력 일부를 거부해야 함
- 정확한 거부 임계값 계산에는 비용이 큰 나머지 연산이 필요함
- 표본 추출기를 반복 사용한다면 초기 설정 비용으로 감당할 수 있음
- 값 하나만 생성할 때는 이 비용이 상대적으로 커짐
rand
는 이러한 차이를 UniformSampler
특성으로 노출함
는 임계값을 미리 계산해 편향 없이 표본을 추출함
Rng::random_range
는 초기 설정을 피하려고 별도의 sample_single
또는 sample_single_inclusive
훅을 사용함
- 기본 기능에서는 일회성 단축 경로가 조금 편향된 두 번째 알고리듬을 사용함
- 선택적
unbiased
기능은 이를 더 복잡한 반복 버전으로 교체함
urandom
은 임계값을 지연 계산해 재사용 및 일회성 범위 모두에 하나의 비편향 곱셈·거부 구현을 사용함
- 별도 메서드나 두 번째 알고리듬, 선행 설정 비용, 편향된 고속 경로 없이 동일한 구현으로 재사용 분포와 일회성 범위를 처리함
500..20_000
범위에서 1,000개를 추출한 벤치마크 결과는 다음과 같음
: rand
1,098ns, urandom
950ns
1,079ns, urandom
942ns
rand
결과는 기본 기능 기준이므로 더 빠른 일회성 행도 약간 편향된 경로인 반면, urandom
은 비편향 상태로 두 경로보다 빨랐음
릴리스와 아키텍처를 아우르는 재현성
urandom
은 재현성을 공개 계약의 일부로 취급함
-
같은 명시적 시드와 같은 저수준 RNG 호출 순서가 주어지면 결정론적 생성기의 원시 출력이 유지됨
-
지원 아키텍처와 SemVer 호환 릴리스 전체에서 안정성을 보장함
-
64비트 서버와 32비트 WebAssembly 클라이언트가 재생을 위한 동일한 생성기 기반을 사용할 수 있음
-
이 호환성을 유지하기 위해 32비트 아키텍처에서는 성능을 희생함
rand
의 재현성 정책보다 강한 보장임
rand
의 이식 가능한 생성기와 표본 추출 알고리듬은 마이너 릴리스에서 출력이 달라질 수 있음
SmallRng
과 StdRng
은 명시적으로 이식 가능하지 않으며 플랫폼이나 라이브러리 릴리스에 따라서도 바뀔 수 있음
선택의 대가와 적용 기준
urandom
은 일반 연산을 Random
에 모아 확장 특성 없이 쉽게 찾을 수 있게 함
- 생성기와 분포를 함께 설계해 더 저렴한 Xoshiro 출력 경로와 하나의 비편향 균등 표본 추출 경로를 구현함
- 명시적으로 시드가 지정된 생성기의 안정적인 원시 스트림은
결정론적 게임과 시뮬레이션에 활용할 수 있음
- 대신 임의 생성기를 가져올 수 없으며,
rand
가 제공하는 더 큰 분포 목록과 서드파티 통합 생태계도 갖추지 못함
가 적합하고, 작은 API 표면·발견성·통합된 최적화·강한 재현성 정책을 선호하면 urandom
을 선택할 수 있음
- 패키지는 crates.io, API 문서, GitHub 소스에서 확인할 수 있음
댓글과 토론