首页 > 解决方案 > 不同步的 math/rand 的更快替代方案

问题描述

我正在尝试优化我的遗传算法。这使用了大量的随机数选择(随机突变等)。

我决定使用 CPU 分析器:

import (
    "runtime/pprof"
)

var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")

func main() {

    if *cpuprofile != "" {
        fmt.Println(*cpuprofile)
        f, err := os.Create(*cpuprofile)
        if err != nil {
            log.Fatal(err)
        }
        _ = pprof.StartCPUProfile(f)
        defer pprof.StopCPUProfile()
    }
    ***app logic***

我很惊讶地看到 CPU 使用率的主要贡献者之一是sync.(*Mutex).Unlock,特别是因为我在我的应用程序中的任何时候都没有使用过线程或 goroutines

pprof 结果

一些挖掘揭示了瓶颈是由 math/rand 中的默认源同步引起的。

有没有更快的方法来生成具有非同步/阻塞函数的随机数?

真正的随机性/准确的伪随机性对于这个应用程序来说并不那么重要,但如果我没有连续多次获得完全相同的数字,那将是首选。

标签: go

解决方案


如您所见,包的默认“随机源”math/rand锁定源,适用于并发 goroutine。您需要使用NewSourcefunction为每个 goroutine 创建一个新源,然后使用New从中创建一个随机数生成器。来自这个新生成器的伪随机数将与(单个)锁定源的工作方式相同,除了每个生成器如果从相同的种子开始,将产生自己的相同生成的数字流。

因此,您需要确保您提供的每个种子NewSource都是唯一的,以便每个流都不同。


推荐阅读