# Cupy和numpy的比较 ## Cupy是使用NVIDIA CUDA核心进行加速运算,因为GPU上有好多CUDA核心,相比CPU可以同时并行更多的线程,因此可以大大提高运算速度,当数据量达到千万级时,用cupy会大大增加运算速度。 该作业我主要是验证以上观点,通过比较`cupy`和`numpy`在不同矩阵大小下进行加法和乘法的运算时间来验证该观点。 ## 实验 ### 加法 从 1x1 的大小开始生成随机数矩阵,每次对矩阵的长和宽分别 x2 以扩大矩阵,每个矩阵大小下分别用 `cupy` 和 `numpy` 分别进行十次矩阵相加运算,最后比较他们的平均运算时间(不包括矩阵生成,只包括运算)。得到的结果如下, ``` 目前矩阵大小为1x1=1 cupy 加法的平均执行时间是 0.000059 s numpy 加法的平均执行时间是 0.000004 s 目前矩阵大小为2x2=4 cupy 加法的平均执行时间是 0.000011 s numpy 加法的平均执行时间是 0.000003 s 目前矩阵大小为4x4=16 cupy 加法的平均执行时间是 0.000012 s numpy 加法的平均执行时间是 0.000003 s 目前矩阵大小为8x8=64 cupy 加法的平均执行时间是 0.000012 s numpy 加法的平均执行时间是 0.000005 s 目前矩阵大小为16x16=256 cupy 加法的平均执行时间是 0.000013 s numpy 加法的平均执行时间是 0.000004 s 目前矩阵大小为32x32=1024 cupy 加法的平均执行时间是 0.000014 s numpy 加法的平均执行时间是 0.000005 s 目前矩阵大小为64x64=4096 cupy 加法的平均执行时间是 0.000015 s numpy 加法的平均执行时间是 0.000006 s 目前矩阵大小为128x128=16384 cupy 加法的平均执行时间是 0.000014 s numpy 加法的平均执行时间是 0.000013 s 目前矩阵大小为256x256=65536 cupy 加法的平均执行时间是 0.000014 s numpy 加法的平均执行时间是 0.000039 s 目前矩阵大小为512x512=262144 cupy 加法的平均执行时间是 0.000023 s numpy 加法的平均执行时间是 0.000195 s 目前矩阵大小为1024x1024=1048576 cupy 加法的平均执行时间是 0.000025 s numpy 加法的平均执行时间是 0.001306 s 目前矩阵大小为2048x2048=4194304 cupy 加法的平均执行时间是 0.000031 s numpy 加法的平均执行时间是 0.010306 s 目前矩阵大小为4096x4096=16777216 cupy 加法的平均执行时间是 0.000069 s numpy 加法的平均执行时间是 0.036332 s 目前矩阵大小为8192x8192=67108864 cupy 加法的平均执行时间是 0.000131 s numpy 加法的平均执行时间是 0.140579 s 目前矩阵大小为16384x16384=268435456 cupy 加法的平均执行时间是 0.003624 s numpy 加法的平均执行时间是 0.565655 s ......(显存爆了)...... ``` 可以看到一开始用小矩阵进行加法运算时,`cupy` 运算速度时不及 `numpy` 的,当矩阵大小达到 128x128 时,其速度相近了。当矩阵大小更大时,`cupy` 的优势体现出来了,`cupy` 的运算速度比 `numpy` 快了百倍。 ### 乘法 乘法的测试方法也和加法一样,只是 `add(x, y)` 替换成了 `multiply(x, y)`。具体结果如下, ``` 目前矩阵大小为1x1=1 cupy 乘法的平均执行时间是 0.000060 s numpy 乘法的平均执行时间是 0.000004 s 目前矩阵大小为2x2=4 cupy 乘法的平均执行时间是 0.000012 s numpy 乘法的平均执行时间是 0.000003 s 目前矩阵大小为4x4=16 cupy 乘法的平均执行时间是 0.000012 s numpy 乘法的平均执行时间是 0.000003 s 目前矩阵大小为8x8=64 cupy 乘法的平均执行时间是 0.000012 s numpy 乘法的平均执行时间是 0.000003 s 目前矩阵大小为16x16=256 cupy 乘法的平均执行时间是 0.000013 s numpy 乘法的平均执行时间是 0.000004 s 目前矩阵大小为32x32=1024 cupy 乘法的平均执行时间是 0.000013 s numpy 乘法的平均执行时间是 0.000004 s 目前矩阵大小为64x64=4096 cupy 乘法的平均执行时间是 0.000013 s numpy 乘法的平均执行时间是 0.000006 s 目前矩阵大小为128x128=16384 cupy 乘法的平均执行时间是 0.000013 s numpy 乘法的平均执行时间是 0.000014 s 目前矩阵大小为256x256=65536 cupy 乘法的平均执行时间是 0.000014 s numpy 乘法的平均执行时间是 0.000043 s 目前矩阵大小为512x512=262144 cupy 乘法的平均执行时间是 0.000021 s numpy 乘法的平均执行时间是 0.000189 s 目前矩阵大小为1024x1024=1048576 cupy 乘法的平均执行时间是 0.000025 s numpy 乘法的平均执行时间是 0.001378 s 目前矩阵大小为2048x2048=4194304 cupy 乘法的平均执行时间是 0.000029 s numpy 乘法的平均执行时间是 0.010370 s 目前矩阵大小为4096x4096=16777216 cupy 乘法的平均执行时间是 0.000066 s numpy 乘法的平均执行时间是 0.041170 s 目前矩阵大小为8192x8192=67108864 cupy 乘法的平均执行时间是 0.000127 s numpy 乘法的平均执行时间是 0.161565 s 目前矩阵大小为16384x16384=268435456 cupy 乘法的平均执行时间是 0.000871 s numpy 乘法的平均执行时间是 0.651580 s ......(显存爆了)...... ``` 得出的结论也和加法相同,但我注意到 `cupy` 在 16384x16384 量级的乘法运算上要比加法运算快 4 倍,这是什么原因呢?照理来说,两个运算时间应该相近才对,于是我又在该大小的矩阵乘法下运行了100次加法和乘法,结果如下, ``` 目前矩阵大小为16384x16384=268435456 cupy 加法的平均执行时间是 0.001242 s numpy 加法的平均执行时间是 0.577567 s cupy 乘法的平均执行时间是 0.001297 s numpy 乘法的平均执行时间是 0.669743 s ``` 可能是因为10次样本太少,导致统计出现了一些偏差,在100次下,`cupy` 乘法和加法的运算时间相近。 ## 结论 当数据量大于万级(128x128=16384)时,`cupy` 的运算速度就会超越 `numpy`;当数据量大于百万级(1024x1024=1048576)时,`cupy` 的运算速度远超 `numpy`。 ## 附录 具体代码: - [hello_cupy.py](./hello_cupy.py)