The function random is a bit slow, can it be optimized?
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
SBCL |
Invalid
|
Undecided
|
Unassigned |
Bug Description
Hi,
Random numbers are frequently used in machine learning algorithms, but the random function of sbcl is a bit slow. Can it be optimized?
(time (dotimes (i 1000000)
(random 1.0 (make-random-state t))))
Evaluation took:
135.454 seconds of real time
135.443309 seconds of total run time (19.848173 user, 115.595136 system)
[ Real times consist of 0.095 seconds GC time, and 135.359 seconds non-GC time. ]
[ Run times consist of 0.093 seconds GC time, and 135.351 seconds non-GC time. ]
99.99% CPU
393,361,050,731 processor cycles
3,423,087,968 bytes consed
In src/code/
#-win32
(defun os-random-seed ()
(or
;; On unices, we try to read from /dev/urandom and pass the results
;; to our (simple-array (unsigned-byte 32) (*)) processor below.
;; More than 256 bits would provide a false sense of security.
;; If you need more bits than that, you probably also need
;; a better algorithm too.
(ignore-errors
(with-open-file (r "/dev/urandom" :element-type '(unsigned-byte 32)
(let ((a (make-array '(8) :element-type '(unsigned-byte 32))))
(aver (= 8 (read-sequence a r)))
a)))
(fallback-
))
(defun fallback-
;; When /dev/urandom is not available, we make do with time and pid
;; Thread ID and/or address of a CONS cell would be even better, but...
;; [ADDRESS-
(/show0 "No /dev/urandom, using randomness from time and pid")
(+ (get-internal-
(ash (sb-unix:
Can these two functions be improved like this?
#-win32
(defun os-random-seed ()
(or
;; On unices, we try to read from /dev/urandom and pass the results
;; to our (simple-array (unsigned-byte 32) (*)) processor below.
;; More than 256 bits would provide a false sense of security.
;; If you need more bits than that, you probably also need
;; a better algorithm too.
(fallback-
(ignore-errors
(with-open-file (r "/dev/urandom" :element-type '(unsigned-byte 32)
(let ((a (make-array '(8) :element-type '(unsigned-byte 32))))
(aver (= 8 (read-sequence a r)))
a)))
))
(defun fallback-
;; When /dev/urandom is not available, we make do with time and pid
;; Thread ID and/or address of a CONS cell would be even better, but...
;; [ADDRESS-
(/show0 "No /dev/urandom, using randomness from time and pid")
(multiple-
(
(+ sec (ash usec 8))))
Now,
(time (dotimes (i 1000000)
(random 1.0 (make-random-state t))))
Evaluation took:
3.991 seconds of real time
3.993465 seconds of total run time (3.980038 user, 0.013427 system)
[ Real times consist of 0.070 seconds GC time, and 3.921 seconds non-GC time. ]
[ Run times consist of 0.069 seconds GC time, and 3.925 seconds non-GC time. ]
100.05% CPU
11,592,835,590 processor cycles
2,543,946,064 bytes consed
Best regards!
Don't do (make-random-state t) on each iteration.