PARL 是一个高性能、灵活的强化学习框架。PARL的目标是构建一个可以完成复杂任务的智能体。在PARL中提供了简易高效的并行接口,只要一个修饰符(parl.remote_class)就可以帮助用户实现自己的并行算法。
下面我们用最近的飞桨2.2.0RC版本进行实验展示,这个版本比正式版本会多一些输出信息。
最新决定:还是用2.1.2版本进行展示,最新版本实在难以掌控。2021.11.9
飞桨升级到2.2正式发行版了,经测试本项目运行正常,因此升级到2.2版本。 2021.11.10日
启动一个PARL集群可以通过执行下面的 xparl 命令:
xparl start --port 6006
这个命令会启动一个主节点(master)来管理集群的计算资源,同时会把本地机器的CPU资源加入到集群中。命令中的6006端口只是作为示例,可以修改成任何有效的端口。启动后可通过 xparl status 查看目前集群有多少CPU资源可用,可以在 xparl start 的命令中加入选项 --cpu_num [CPU_NUM] (例如:–cpu_num 10)指定本机加入集群的CPU数量。
比如设置加入集群的cpu数量为2:
xparl start --port 6006 --cpu_num 2
通过执行下面命令可以让其它资源加入集群:
xparl connect --address localhost:6006
下面就在AIStudio环境下实践一下
首先安装需要的库文件:
# 安装需要的库,大约38秒时间 !pip install pip -U !pip install blackhole pyarrow -Uq # !pip install pyarrow -Uq # !pip install parl -U
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple Collecting pip [?25l Downloading https://pypi.tuna.tsinghua.edu.cn/packages/a4/6d/6463d49a933f547439d6b5b98b46af8742cc03ae83543e4d7688c2420f8b/pip-21.3.1-py3-none-any.whl (1.7MB) [K |████████████████████████████████| 1.7MB 2.3MB/s eta 0:00:01 [?25hInstalling collected packages: pip Found existing installation: pip 19.2.3 Uninstalling pip-19.2.3: Successfully uninstalled pip-19.2.3 Successfully installed pip-21.3.1
# 大约需要50秒时间,至尊版9秒 !pip install pyarrow blackhole parl numpy gym atari-py -Uq # !pip install parl -U -q # !pip install gym[accept-rom-license] -q
[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts. paddlefsl 1.0.0 requires numpy~=1.19.2, but you have numpy 1.21.4 which is incompatible. paddlefsl 1.0.0 requires pillow==8.2.0, but you have pillow 7.1.2 which is incompatible. paddlefsl 1.0.0 requires requests~=2.24.0, but you have requests 2.22.0 which is incompatible.[0m
让我们看下当前飞桨版本,并通过创建一个张量验证飞桨是否正常工作。若有报错,需要查找错误原因并解决问题。
看到这个就证明飞桨正常工作:
Tensor(shape=[2], dtype=int64, place=CUDAPlace(0), stop_gradient=True, [0, 1])
会有极小的概率碰到AIStudio出问题,通过验证张量就能提前发现问题,这时候把项目停止,稍等一会儿再启动,大概率就能恢复正常了。
import paddle paddle.utils.run_check() print(paddle.__version__) print(paddle.to_tensor([0,1]))
Running verify PaddlePaddle program ... W1110 20:48:41.470507 904 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 10.1, Runtime API Version: 10.1 W1110 20:48:41.475559 904 device_context.cc:465] device: 0, cuDNN Version: 7.6. PaddlePaddle works well on 1 GPU. PaddlePaddle works well on 1 GPUs. PaddlePaddle is installed successfully! Let's start deep learning with PaddlePaddle now. 2.2.0 Tensor(shape=[2], dtype=int64, place=CUDAPlace(0), stop_gradient=True, [0, 1]) /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/tensor/creation.py:130: DeprecationWarning: `np.object` is a deprecated alias for the builtin `object`. To silence this warning, use `object` by itself. Doing this will not modify any behavior and is safe. Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations if data.dtype == np.object:
使用命令xparl start --port 6006
来启动并行计算集群,可以设置cpu数量,比如我们这里设置为5 --cpu_num 5
# !xparl start --port 6006 --cpu_num 5 import os os.system("nohup xparl start --port 6006 --cpu_num 5") # os.system("nohup xparl start --port 6006")
# 查看6006端口服务是否启动 !netstat -an |grep 6006
tcp 0 0 0.0.0.0:6006 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:6006 127.0.0.1:33754 ESTABLISHED tcp 0 0 127.0.0.1:33752 127.0.0.1:6006 ESTABLISHED tcp 0 0 127.0.0.1:33754 127.0.0.1:6006 ESTABLISHED tcp 0 0 127.0.0.1:6006 127.0.0.1:33752 ESTABLISHED
启动集群后,就可以直接使用集群了,如果CPU资源不够用,可以在任何时候和任何机器(包括本机或其他机器)上,通过执行 xparl connect 命令把更多CPU资源加入到集群中。
xparl connect --address localhost:6006
# !xparl connect --address localhost:6006
看看集群服务是否正常启动,观察vacant cpus数量是否与设置的一样。
# Cluster localhost:6006 has 0 used cpus, 0 vacant cpus.
import os os.system("xparl status")
在master机器上运行 xparl stop 命令即可关闭集群程序。当master节点退出后,与之关联的worker节点也会自动退出并结束相关程序。
在本项目中,因为是用os.system启动的,所以关闭的时候也要用os.system命令。关闭之后,再用!netstat -an |grep 6006
命令,没有输出,证明xparl集群已经关闭。
# os.system("xparl stop")
用命令测试
netstat -an |grep 6006
若没有匹配输出,证明xparl服务已经关闭,有时候需要等待一段时间再来执行这条命令,确认服务已经关闭
# 没有匹配输出,证明xparl服务已经关闭 # !netstat -an |grep 6006
# os.system("xparl start --port 6006 --cpu_num 3") # !netstat -an |grep 6006
使用 parl.remote_class 修饰一个类,之后这个类就被转化为可以运行在其他CPU或者机器上的类。
调用 parl.connect 函数来初始化并行通讯,通过这种方式获取到的实例和原来的类是有同样的函数的。由于这些类是在别的计算资源上运行的,执行这些函数 不再消耗当前线程计算资源 。
下面是一个PARL集群的例子,只要加上@parl.remote_class
和parl.connect("localhost:6008")
这两句话即可。注意并行代码的语句不会在本地输出信息,比如例子中的打印语句。
下面cell将代码写入test.py问题,然后执行该文件,会发现改程序的hello_world并没有打印语句,但是调用add有返回两个数的加和。
%%writefile test.py import warnings warnings.filterwarnings("ignore") import parl @parl.remote_class class Actor(object): def hello_world(self): print("Hello world.") def add(self, a, b): return a + b # Connect to the master node. parl.connect("localhost:6006") actor = Actor() actor.hello_world()# no log in the current terminal, as the computation is placed in the cluster. tmp = actor.add(1, 2) # return 3 print("1 add 2 is ", tmp)
Writing test.py
!python test.py
[32m[11-10 20:49:00 MainThread @logger.py:242][0m Argv: test.py [32m[11-10 20:49:01 MainThread @utils.py:73][0m paddlepaddle version: 2.2.0. [32m[11-10 20:49:01 MainThread @client.py:440][0m Remote actors log url: http://172.29.153.13:57498/logs?client_id=172.29.153.13_34728_1636548541 1 add 2 is 3
众所周知,Python下的多线程让人一言难尽。因为全局解释器锁(GIL)的存在,导致python的多线程是伪多线程,在计算量大的时候,跟单线程比没有优势甚至还有可能更慢。下面代码就是比较了普通代码、普通多线程代码、PARL并行加速代码以及并行加速简化代码。普通代码和普通多线程代码的用时差不多,普通代码9.79秒,普通多线程9.20秒,xparl并行4.95秒。而且有时候普通多线程反而会比普通代码还要更慢一点。
以下三个文件,分别为普通代码normal.py 普通多线程multi.py 以及xparl并行加速xparlpro.py
%%writefile normal.py class A(object): def run(self): ans = 0 for i in range(50000000): ans += i a = A() for _ in range(4): a.run()
Writing normal.py
!python normal.py # 9.79秒
%%writefile multi.py import threading class A(object): def run(self): ans = 0 for i in range(50000000): ans += i threads = [] for _ in range(4): a = A() th = threading.Thread(target=a.run) th.start() threads.append(th) for th in threads: th.join()
Writing multi.py
!python multi.py # 9.20秒
%%writefile xparlpro.py import threading import parl @parl.remote_class class A(object): def run(self): ans = 0 for i in range(50000000): ans += i threads = [] parl.connect("localhost:6006") for _ in range(4): a = A() th = threading.Thread(target=a.run) th.start() threads.append(th) for th in threads: th.join() print("OK")
Writing xparlpro.py
!python xparlpro.py # 4.95秒
通过寻找质因数的方式破解密码看似几乎不可能,但如果使用正确的算法-Fermat因式分解法,这将变得很容易。
基本思路就是使用如下公式把整数N(奇数)分解为c和d两个数
N
=
c
d
=
(
a
+
b
)
(
a
−
b
)
=
a
2
−
b
2
N = cd =(a+b)(a-b) = a^2 -b^2
N=cd=(a+b)(a−b)=a2−b2
递归的应用这个因式分解,直至得到需要的质因数.
费马因式分解的问题是:不适用于合数的两个质因数差别很大的情况,在这种情况下,要么速度比较慢,要么为了提高速度就会错认该合数是质数。下面的代码就是为了提高速度,在两个质因数相差超过LIM = 10 ** 6
的时候会误判。
普通程序代码如下,我们会发现大数的质因数分解运算速度非常快:
import numpy as np N = 60851475143*13 # 这个数无法快速分解 N = 60851475143 # 这个数无法快速和慢速分解,很可能是质数 N = 123456891 # 不是质数,但是会被误认为是质数 N = 600851475143 # 这个数可以分解 LIM = 10 ** 6 def factor(n, LIM=10**6): # LIM = 10 ** 6 a = np.ceil(np.sqrt(n)) lim = min(n,LIM) a = np.arange(a,a+lim) b2 = a ** 2 - n fractions = np.modf(np.sqrt(b2))[0] indices = np.where(fractions == 0 ) # 有些数可能找不到符合要求的位置值 if indices[0].size == 0: # 找不到的可能是质数,直接返回 print(n) return n a = np.ravel(np.take(a, indices))[0] a = int(a) b = np.sqrt(a ** 2 -n) b = int(b) c = a + b d = a - b if c == 1 or d ==1 : return n print (c,d) factor(c) factor(d) factor(N)
1234169 486847 1471 839 6857 71
%%writefile prime.py import numpy as np N = 60851475143*13 # 这个数无法快速分解 N = 60851475143 # 这个数无法快速和慢速分解,很可能是质数 N = 600851475143 # 这个数可以分解 LIM = 10 ** 6 def factor(n, LIM=10**6): a = np.ceil(np.sqrt(n)) lim = min(n,LIM) a = np.arange(a,a+lim) b2 = a ** 2 - n fractions = np.modf(np.sqrt(b2))[0] indices = np.where(fractions == 0 ) # 有些数可能找不到符合要求的位置值 if indices[0].size == 0: # 找不到的可能是质数,直接返回 print(n) return n a = np.ravel(np.take(a, indices))[0] a = int(a) b = np.sqrt(a ** 2 -n) b = int(b) c = a + b d = a - b if c == 1 or d ==1 : return n print (c,d) factor(c) factor(d) factor(N)
Writing prime.py
同样的代码,使用python prime.py
的形式运行时需要400ms左右,比直接在cell里面执行慢了很多。
!python prime.py
1234169 486847 1471 839 6857 71 6857 71
# 又慢又费内存的费马因式分解,理论上在内存和时间足够的情况下,可以分解任意奇数。 import numpy as np N = 60851475143 # 这是质数,大质数会爆内存 # N = 600851475143 N = 123456891 # N = 3 ** 27 # N = 6857 * 3 LIM = max(10 **6, N /3) def factormem(n): a = np.ceil(np.sqrt(n)) lim = min(n,LIM) a = np.arange(a,a+lim) b2 = a ** 2 - n fractions = np.modf(np.sqrt(b2))[0] indices = np.where(fractions == 0 ) if indices[0].size == 0: return n a = np.ravel(np.take(a, indices))[0] a = int(a) b = np.sqrt(a ** 2 -n) b = int(b) c = a + b d = a - b if c == 1 or d ==1 : return print (c,d) factormem(c) factormem(d) factormem(N)
41152297 3
import numpy as np def factor(n, LIM=10**6): # LIM = 10 ** 6 a = np.ceil(np.sqrt(n)) lim = min(n,LIM) a = np.arange(a,a+lim) b2 = a ** 2 - n fractions = np.modf(np.sqrt(b2))[0] indices = np.where(fractions == 0 ) # 有些数可能找不到符合要求的位置值 if indices[0].size == 0: # 找不到的可能是质数,直接返回 print(n) return n a = np.ravel(np.take(a, indices))[0] a = int(a) b = np.sqrt(a ** 2 -n) b = int(b) c = a + b d = a - b if c == 1 or d ==1 : return n # print (c,d) factor(c) factor(d) class Primetest(object): def __init__(self, EPOCH): self.epoch = EPOCH def run(self, N): for i in range(self.epoch): factor(N) for _ in range(4): test = Primetest(100) # 100 test.run(600851475143) # 11秒
%%writefile primenormal.py import parl import threading import numpy as np def factor(n, LIM=10**6): # LIM = 10 ** 6 a = np.ceil(np.sqrt(n)) lim = min(n,LIM) a = np.arange(a,a+lim) b2 = a ** 2 - n fractions = np.modf(np.sqrt(b2))[0] indices = np.where(fractions == 0 ) # 有些数可能找不到符合要求的位置值 if indices[0].size == 0: # 找不到的可能是质数,直接返回 print(n) return n a = np.ravel(np.take(a, indices))[0] a = int(a) b = np.sqrt(a ** 2 -n) b = int(b) c = a + b d = a - b if c == 1 or d ==1 : return n # print (c,d) factor(c) factor(d) # @parl.remote_class class PrimeParl(object): def __init__(self, EPOCH=100): self.epoch = EPOCH def run(self, N): for i in range(self.epoch): factor(N) # if __name__ == "__main__": # parl.connect("localhost:6006") # parl.connect("127.0.0.1:6006") threads = [] for _ in range(2): test = PrimeParl() test.run(600851475143) # 15秒 print("OK")
Writing primenormal.py
!python primenormal.py
[32m[11-10 20:49:40 MainThread @logger.py:242][0m Argv: primenormal.py [32m[11-10 20:49:42 MainThread @utils.py:73][0m paddlepaddle version: 2.2.0. /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/parl/remote/communication.py:38: FutureWarning: 'pyarrow.default_serialization_context' is deprecated as of 2.0.0 and will be removed in a future version. Use pickle or the pyarrow IPC functionality instead. context = pyarrow.default_serialization_context() OK
%%writefile primethread.py import parl import threading import numpy as np def factor(n, LIM=10**6): # LIM = 10 ** 6 a = np.ceil(np.sqrt(n)) lim = min(n,LIM) a = np.arange(a,a+lim) b2 = a ** 2 - n fractions = np.modf(np.sqrt(b2))[0] indices = np.where(fractions == 0 ) # 有些数可能找不到符合要求的位置值 if indices[0].size == 0: # 找不到的可能是质数,直接返回 print(n) return n a = np.ravel(np.take(a, indices))[0] a = int(a) b = np.sqrt(a ** 2 -n) b = int(b) c = a + b d = a - b if c == 1 or d ==1 : return n # print (c,d) factor(c) factor(d) # @parl.remote_class class PrimeParl(object): def __init__(self, EPOCH=100): self.epoch = EPOCH def run(self, N): for i in range(self.epoch): factor(N) # if __name__ == "__main__": # parl.connect("localhost:6006") # parl.connect("127.0.0.1:6006") threads = [] for _ in range(2): test = PrimeParl() th = threading.Thread(target=test.run(600851475143)) # 15秒 th.start() threads.append(th) for th in threads: th.join() print("OK")
Writing primethread.py
!python primethread.py
[32m[11-10 20:49:55 MainThread @logger.py:242][0m Argv: primethread.py [32m[11-10 20:49:57 MainThread @utils.py:73][0m paddlepaddle version: 2.2.0. /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/parl/remote/communication.py:38: FutureWarning: 'pyarrow.default_serialization_context' is deprecated as of 2.0.0 and will be removed in a future version. Use pickle or the pyarrow IPC functionality instead. context = pyarrow.default_serialization_context() OK
%%writefile primexparl.py import parl import threading import numpy as np def factor(n, LIM=10**6): # LIM = 10 ** 6 a = np.ceil(np.sqrt(n)) lim = min(n,LIM) a = np.arange(a,a+lim) b2 = a ** 2 - n fractions = np.modf(np.sqrt(b2))[0] indices = np.where(fractions == 0 ) # 有些数可能找不到符合要求的位置值 if indices[0].size == 0: # 找不到的可能是质数,直接返回 print(n) return n a = np.ravel(np.take(a, indices))[0] a = int(a) b = np.sqrt(a ** 2 -n) b = int(b) c = a + b d = a - b if c == 1 or d ==1 : return n # print (c,d) factor(c) factor(d) @parl.remote_class class PrimeParl(object): def __init__(self, EPOCH=100): self.epoch = EPOCH def run(self, N): for i in range(self.epoch): factor(N) # if __name__ == "__main__": parl.connect("localhost:6006") # parl.connect("127.0.0.1:6006") threads = [] for _ in range(2): test = PrimeParl() th = threading.Thread(target=test.run(600851475143)) # 15秒 th.start() threads.append(th) for th in threads: th.join() print("OK")
Writing primexparl.py
!python primexparl.py
XPARL对numpy的加速不明显,可能原因是numpy本身已经进行了并行处理。同样python自己的多线程也无法提速numpy。
主要介绍可以看官网介绍,以及参考AI在打野的项目
主要思想是将模型分为两部分:一个用于基于状态计算动作,另一个用于估计动作的Q值。
Actor演员将状态作为输入并输出最佳动作。 它实质上是通过控制代理的行为来学习最佳策略 (基于策略) 。 另一方面,Critic评论家通过计算值函数评估动作 (基于值)来 。 这两个模型参加了一场比赛,随着时间的流逝,他们各自的角色都变得更好。 结果是,与单独使用两种方法相比,整个体系结构将学会更有效地玩游戏。
tail -f train_log/train/log.log
来查看下图图片中第三个就是PongNoFrameskip-v4的训练图,可以看到训练500万-600万左右,reward就达到20左右。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Clt5eeLx-1637295400934)(work/result_a2c_paddle0.png)]
!pip install ale-py -q !pip install gym[accept-rom-license] -q
# 开始训练 !python work/train.py
通过修改work/a2c_config.py文件中的actor_num参数,可以设定并行的actor数目。下面是不同数目的log信息。
‘actor_num’: 2
[10-27 15:02:11 MainThread @train.py:176] {'sample_steps': 55000, 'max_episode_rewards': -20.0, 'mean_episode_rewards': -20.833333333333332, 'min_episode_rewards': -21.0, 'max_episode_steps': 3844, 'mean_episode_steps': 3402.3333333333335, 'min_episode_steps': 3132, 'total_loss': 8.261118, 'pi_loss': 2.724749, 'vf_loss': 18.02188, 'entropy': 347.45706, 'learn_time_s': 0.021220602989196778, 'elapsed_time_s': 132, 'lr': 0.0009945000000000002, 'entropy_coeff': -0.01} [10-27 15:02:21 MainThread @train.py:176] {'sample_steps': 59800, 'max_episode_rewards': -17.0, 'mean_episode_rewards': -19.833333333333332, 'min_episode_rewards': -21.0, 'max_episode_steps': 5043, 'mean_episode_steps': 3861.6666666666665, 'min_episode_steps': 3132, 'total_loss': 10.759564, 'pi_loss': 5.258734, 'vf_loss': 18.009485, 'entropy': 350.3912, 'learn_time_s': 0.020256004333496093, 'elapsed_time_s': 142, 'lr': 0.00099402, 'entropy_coeff': -0.01}
‘actor_num’: 4
[11-09 20:32:17 MainThread @train.py:176] {'sample_steps': 24400, 'max_episode_rewards': -20.0, 'mean_episode_rewards': -20.6, 'min_episode_rewards': -21.0, 'max_episode_steps': 3703, 'mean_episode_steps': 3452.8, 'min_episode_steps': 3305, 'total_loss': -25.857307, 'pi_loss': -40.658012, 'vf_loss': 42.31675, 'entropy': 635.76697, 'learn_time_s': 0.0581492048795106, 'elapsed_time_s': 30, 'lr': 0.00099756, 'entropy_coeff': -0.01} [11-09 20:32:27 MainThread @train.py:176] {'sample_steps': 32800, 'max_episode_rewards': -20.0, 'mean_episode_rewards': -20.75, 'min_episode_rewards': -21.0, 'max_episode_steps': 3377, 'mean_episode_steps': 3302.75, 'min_episode_steps': 3169, 'total_loss': -16.47223, 'pi_loss': -30.15582, 'vf_loss': 39.746986, 'entropy': 618.9895, 'learn_time_s': 0.058261028150232826, 'elapsed_time_s': 40, 'lr': 0.00099672, 'entropy_coeff': -0.01}
可以看到’actor_num’: 2时每个log间隔10秒 大约4800步(每次间隔的步数有浮动),这样一次训练1000万步就需要 1000万/4800 * 10 = 3000*10 = 300000秒 = 5.78小时
最终实际耗时为6小时54分钟。
当’actor_num’: 4时,每个log间隔10秒,大约8400步 。这样一次训练1000万步大约需要3.3小时。
通过以上的对比实验这样可以看到xparl确实起了并行加速作用,‘actor_num’ 4比2时要快了75%
运行:
!pip install ale-py
f"We're Unable to find the game \"{self._game}\". Note: Gym no longer distributes ROMs. " gym.error.Error: We're Unable to find the game "Pong". Note: Gym no longer distributes ROMs. If you own a license to use the necessary ROMs for research purposes you can download them via `pip install gym[accept-rom-license]`. Otherwise, you should try importing "Pong" via the command `ale-import-roms`. If you believe this is a mistake perhaps your copy of "Pong" is unsupported. To check if this is the case try providing the environment variable `PYTHONWARNINGS=default::ImportWarning:ale_py.roms`. For more information see: https://github.com/mgbellemare/Arcade-Learning-Environment#rom-management
安装 !pip install gym[accept-rom-license]
File "/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/dygraph/tracer.py", line 45, in trace_op not stop_gradient) OSError: (External) Cuda error(2), out of memory. [Advise: The API call failed because it was unable to allocate enough memory to perform the requested operation. ] (at /paddle/paddle/fluid/platform/stream/cuda_stream.cc:49)
自己写了一个tensor数据data1 = paddle.ones(shape=[3, 2])
,还是报这个错,证明是环境问题。大重启环境。
大环境重启后,测试通过
原来这两句话还是要单独再执行一下
!pip install ale-py -q !pip install gym[accept-rom-license]
Exception: Client can not connect to the master, please check if master is started and ensure the input address localhost:6006 is correct.
这是因为还没开xparl服务器。
开启服务xparl start --port 6006 --cpu_num 1
,运行报错:
[10-27 12:45:12 Thread-6 @remote_wrapper.py:175] WRN No vacant cpu resources at the moment, will try 270 times later.
再来一句加上服务xparl connect --address 127.0.0.1:6006
还是报错
把agent数量减少:
'actor_num': 5,
改成2
启动服务用xparl start --port 6006
再进行训练,终于成功了!
但是在使用的时候,一直时好时坏,主要问题就是cpu资源太少。比如有这样的报错
Exception: Can not submit job to the master. Please check if master is still alive.
解决的方法是再手动启动。
---> 14 test = Primeparl(100) --> 653 raise TypeError('{!r} is a built-in class'.format(object)) 654 if ismethod(object): 655 object = object.__func__ TypeError: <class '__main__.PrimeParl'> is a built-in class
解决方法是,把进程放到if name == “main”:里面
Exception: Can not submit job to the master. Please check if master is still alive.
不知道为什么,xparl的服务有几次莫名其妙的没有了。 再手动启动。
<class '__main__.PrimeParl'> is a built-in class
放弃分离代码,改成一体式代码,即将原来cell里的代码写到一个.py文件中。
在普通版本和高端版本里,因为只有2核cpu,xparl非常难调试,很容易出现No vacant cpu resources 的错误。
建议在至尊版下面运行。
在不熟悉的时候,可以通过xparl status以及netstat -an |grep 6006来确认服务端口是否开始,是否有设定数量的空闲cpu资源。
可以使用xparl stop来停止集群服务,但是会有延时。
有时候xparl服务会自己停,这时候就需要再手工启动。xparl start --port 6006 --cpu_num 5
实在不行,停止整个项目,然后再重新进入项目。
个人认为这是因为在AIStudio服务器里面的缘故,在物理机环境下可能就不会碰到这么多问题。
Python的多线程,只适用于非计算密集型任务。只能多任务,但不能计算密集。
让我们荡起双桨,在AI的海洋乘风破浪!
飞桨官网:https://www.paddlepaddle.org.cn
因为水平有限,难免有不足之处,还请大家多多帮助。
作者:段春华, 网名skywalk 或 天马行空,济宁市极快软件科技有限公司的AI架构师,百度飞桨PPDE。
我在AI Studio上获得至尊等级,点亮10个徽章,来互关呀~ https://aistudio.baidu.com/aistudio/personalcenter/thirdview/141218