我准备将Numba与我的AMD GPU一起使用。我从他们网站上可用的最基本的示例开始,使用蒙特卡洛模拟来计算Pi的值。
我对代码进行了一些更改,以使其可以先在GPU上运行,然后在CPU上运行。这样,我只想比较执行代码和验证结果所花费的时间。下面是代码:
from numba import jit
import random
from timeit import default_timer as timer
@jit(nopython=True)
def monte_carlo_pi(nsamples):
acc = 0
for i in range(nsamples):
x = random.random()
y = random.random()
if (x ** 2 + y ** 2) < 1.0:
acc += 1
return 4.0 * acc / nsamples
def monte_carlo_pi_cpu(nsamples):
acc = 0
for i in range(nsamples):
x = random.random()
y = random.random()
if (x ** 2 + y ** 2) < 1.0:
acc += 1
return 4.0 * acc / nsamples
num = int(input())
start = timer()
random.seed(0)
print(monte_carlo_pi(num))
print("with gpu", timer()-start)
start = timer()
random.seed(0)
print(monte_carlo_pi_cpu(num))
print("without gpu", timer()-start)
我期望GPU的性能更好,所以它确实做到了。但是,CPU和CPU的某些结果不匹配。
1000000 # input parameter
3.140836 # gpu_out
with gpu 0.2317520289998356
3.14244 # cpu_out
without gpu 0.39849199899981613
我知道Python不能很好地执行长浮点运算,但是这些仅是小数点后6位,而且我并不期望出现如此大的差异。谁能解释为什么会出现这种差异?
我对您的代码进行了一些重组:
import numpy
from numba import jit
import random
from timeit import default_timer as timer
@jit(nopython=True)
def monte_carlo_pi(nsamples):
random.seed(0)
acc = 0
for i in range(nsamples):
x = random.random()
y = random.random()
if (x ** 2 + y ** 2) < 1.0:
acc += 1
return 4.0 * acc / nsamples
num = 1000000
# run the jitted code once to remove compile time from timing
monte_carlo_pi(10)
start = timer()
print(monte_carlo_pi(num))
print("jitted code", timer()-start)
start = timer()
print(monte_carlo_pi.py_func(num))
print("non-jitted", timer()-start)
结果是:
3.140936
jitted code 0.01403845699996964
3.14244
non-jitted 0.39901430800000526
请注意,您没有在GPU上运行固定代码。该代码已编译,但适用于您的CPU。Pi的计算值不同的原因可能是由于基础随机数生成器的实现方式不同。Numba实际上并没有使用Python的random
模块,而是拥有自己的实现来模仿它。事实上,如果你看看源代码,它看起来好像基于numpy的的随机模块上的numba实现主要设计,然后只需别名random
从该模块,所以如果你换出random.random
了np.random.random
,使用相同的种子,你会得到相同的结果:
@jit(nopython=True)
def monte_carlo_pi2(nsamples):
np.random.seed(0)
acc = 0
for i in range(nsamples):
x = np.random.random()
y = np.random.random()
if (x ** 2 + y ** 2) < 1.0:
acc += 1
return 4.0 * acc / nsamples
结果是:
3.140936
jitted code 0.013946142999998301
3.140936
non-jitted 0.9277294739999888
还有其他一些注意事项:
.py_func
,因此不必重复两次代码。本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句