如何用rapids.ai在GPU中做矩阵点积
Posted
技术标签:
【中文标题】如何用rapids.ai在GPU中做矩阵点积【英文标题】:How to do a matrix dot product in the GPU with rapids.ai 【发布时间】:2019-06-26 02:00:48 【问题描述】:我正在使用CUDF,它是 Nvidia 的 rapids ML 套件的一部分。
使用这个套件我将如何做一个点积?
df = cudf.DataFrame([('a', list(range(20))),
('b', list(reversed(range(20)))),
('c', list(range(20)))])
例如如何使用相同的 cudf 对象在上述 Dataframe 上执行点积?
【问题讨论】:
cudf 还很年轻,尚未实现与 pandas 实现功能平等的目标。如果在您的限制范围内这样做,我会查看 cupy 来代替此任务。 @wbadart cudf 暂时提供了按行执行的内核。 感谢@cwharris,这是个好消息! 【参考方案1】:cuDF Dataframe 提供了一个apply_rows
方法,它能够将方法编译到内核中并在 GPU 上执行。此功能已实现January of last year。
import cudf
import numpy
rows = 20000000
df = cudf.DataFrame([
('a_in', list(range(rows))),
('b_in', list(reversed(range(rows)))),
('c_in', list(range(rows)))
])
def kernel(a_in, b_in, c_in, dot):
for i, (a, b, c) in enumerate(zip(a_in, b_in, c_in)):
dot[i] = a * b * c
df = df.apply_rows(
kernel,
incols=['a_in', 'b_in', 'c_in'],
outcols=dict(dot=numpy.float64),
kwargs=dict()
)
[x for x in df['dot']]
产品
[0.0,
18.0,
68.0,
144.0,
240.0,
350.0,
468.0,
588.0,
704.0,
810.0,
900.0,
968.0,
1008.0,
1014.0,
980.0,
900.0,
768.0,
578.0,
324.0,
0.0]
至于计算点积...
import cudf
import numpy
import pandas
rows = 20000000
values_a = [float(x) for x in list(range(rows))]
values_b = [float(x) for x in list(reversed(range(rows)))]
values_c = [float(x) for x in list(range(rows))]
def create_cudf_dataframe():
return cudf.DataFrame([
('a_in', values_a),
('b_in', values_b),
('c_in', values_c)
])
def create_pandas_dataframe():
return pandas.DataFrame(
data =
'a_in': values_a,
'b_in': values_b,
'c_in': values_c
)
def test_cudf(df = None):
print('\ncomputing dot product using cudf')
def kernel(a_in, b_in, c_in, dot):
for i, (a, b, c) in enumerate(zip(a_in, b_in, c_in)):
dot[i] = a * b * c
if df is None:
print(' - creating dataframe using cudf')
df = create_cudf_dataframe()
df = df.apply_rows(
kernel,
incols=['a_in', 'b_in', 'c_in'],
outcols=dict(dot=numpy.float64),
kwargs=dict(),
cache_key='dot_product_3'
)
dp = df['dot'].sum()
print(dp);
def test_pandas(df = None):
print('\ncomputing dot product using pandas')
if df is None:
print(' - creating dataframe using pandas')
df = create_pandas_dataframe()
a = df['a_in']
b = df['b_in']
c = df['c_in']
dp = a.mul(b).mul(c).sum()
print(dp)
cudf_df = create_cudf_dataframe()
pandas_df = create_pandas_dataframe()
%time test_cudf()
%time test_cudf(cudf_df)
%time test_pandas()
%time test_pandas(pandas_df)
在 ubuntu@18.04 上运行在 i7 6700-k、32GB 内存和 GTX 1080 ti 上的 jupyter 上的性能结果。
computing dot product using cudf
- creating dataframe using cudf
1.333333066666688e+28
CPU times: user 1.78 s, sys: 273 ms, total: 2.06 s
Wall time: 2.05 s
computing dot product using cudf
1.333333066666689e+28
CPU times: user 19.4 ms, sys: 24 ms, total: 43.4 ms
Wall time: 43.1 ms
computing dot product using pandas
- creating dataframe using pandas
1.3333330666666836e+28
CPU times: user 7.81 s, sys: 781 ms, total: 8.59 s
Wall time: 8.57 s
computing dot product using pandas
1.3333330666666836e+28
CPU times: user 125 ms, sys: 120 ms, total: 245 ms
Wall time: 245 ms
【讨论】:
【参考方案2】:我也一直在寻找这个问题的解决方案,我的cuDF/cupy/numba
技能现在可以胜任了:
import cudf
import cupy as cp
x = cudf.DataFrame('a': np.arange(10), 'b': np.arange(10), 'c': np.arange(10))
X = cp.asarray(x.as_gpu_matrix())
y = cudf.DataFrame.from_gpu_matrix((X.T).dot(X))
y.columns = x.columns
print(y)
输出:
a b c
0 285 285 285
1 285 285 285
2 285 285 285
从cudf
到cupy
的转移都是零拷贝!
【讨论】:
以上是关于如何用rapids.ai在GPU中做矩阵点积的主要内容,如果未能解决你的问题,请参考以下文章
无法使用 rapids.ai 版本 21.08 将 cudf、cupy 和 cuml 安装到 colab 中