python cuda cpu中随机种子(一)

最近一直在做A3C框架中的强化学习算法,发现随机种子的设定非常重要。首先,为了代码的可复现性,要设定随机种子,让每次代码跑出来的结果一样。其次,由于A3C框架的特殊性,每个worker(一个子线程)之间要保证其多样性。但是,我在设定完了之后,发现跑出来的结果并不能保证完全一模一样,于是对于seed做了一些实验,得出了一点心得。

首先,说一下几个随机种子:

python&numpy:

random.seed(seed)
np.random.seed(seed)

cpu&gpu:

torch.manual_seed(seed)  # 为cpu设置随机种子
torch.cuda.manual_seed(seed)  # 为当前GPU设置随机种子
torch.cuda.manual_seed_all(seed)  # 为所有GPU设置随机种子

cudnn:(对结果影响不大,会影响性能)

torch.backends.cudnn.deterministic = True
torch.backends.benchmark = False

先说一下为什么实验结果可能每次运行出来的结果不一样:

因为你的代码中有诸如np.random.random()的代码,如果你不设置随机种子,可能每次跑出来的结果都不一样。

下面分别来说说不同的随机种子都对哪些函数进行作用:

首先是对于python和numpy的随机种子,如果是调用random函数或者是np.random族下的函数,只能使用

random.seed(seed)
np.random.seed(seed)

来对随机种子进行设定,使用torch下的随机种子没有作用。

还有就是,得看函数在哪里调用,如果是在类初始化的时候调用的函数,则不同实例,只要是设置的随机种子相同,产生的随机数也相同,如下代码所示:

class test(nn.Module):
    def __init__(self, seed, rank):
        super(test, self).__init__()
        random.seed(seed)
        np.random.seed(seed)
        self.rank = rank
        self.get()

    def get(self):
        for _ in range(5):
            print(self.rank, np.random.randint(0, 5))
def main():
   test_1 = test(0, 0)
   test_2 = test(0, 1)
if __name__ == '__main__':
    main()

上述代码运行的结果是:

可以看出,两个实例随机出来的随机数相同。

如果产生随机数的get函数是从外部调用的,改成如下的代码:

class test(nn.Module):
    def __init__(self, seed, rank):
        super(test, self).__init__()
        random.seed(seed)
        np.random.seed(seed)
        seed_torch(seed)
        self.rank = rank

    def get(self):
        for _ in range(5):
            print(self.rank, np.random.randint(0, 5))
def main():
    test_1 = test(0, 0)
    test_2 = test(0, 1)
    test_1.get()
    test_2.get()

结果如下:

就算是把get函数的调用顺序改变,改成:

def main():
    test_1 = test(0, 0)
    test_2 = test(0, 1)
    test_2.get()
    test_1.get()

产生的随机数也不会变:

如果我把main函数中加入了全局的随机种子,其他不变:

def main():
    random.seed(4)
    np.random.seed(4)
    test_1 = test(0, 0)
    test_2 = test(0, 1)
    test_1.get()
    test_2.get()

结果仍然不变:

可以看出,类中产生的随机数,是每个类的随机种子所决定的。如果去除类初始化中的随机种子,改为在主函数中定义随机种子,如下:

class test(nn.Module):
    def __init__(self, seed, rank):
        super(test, self).__init__()
        self.rank = rank

    def get(self):
        for _ in range(5):
            print(self.rank, np.random.randint(0, 5))
def main():
    random.seed(4)
    np.random.seed(4)
    test_1 = test(0, 0)
    test_2 = test(0, 1)
    test_1.get()
    test_2.get()

结果如下:

可以看出,结果取决于main函数设定的随机种子。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值