暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

内积运算加速方法对比:C++ Numpy GPU

Coggle数据科学 2022-12-27
1717

内积运算

内积(inner product)是一种在向量空间中定义的二元运算,也称为点积、内积或标量积。

内积可以用来表示两个向量之间的相似程度、夹角以及两个向量之间的夹角余弦值。

如果两个向量a和b的内积是正数,则它们夹角小于90°;如果内积是负数,则它们夹角大于90°;如果内积是0

内积与机器学习

在机器学习中,内积运算可以用来表示向量之间的相似程度。内积运算还可以用来表示向量之间的距离。

例如,在文本分类任务中,我们可以将每篇文章看作一个向量,并使用内积运算来计算两篇文章之间的相似程度。

在推荐系统中,我们也可以使用内积运算来计算用户和物品之间的相似程度,从而推荐相似度高的物品给用户。

内积计算加速

内积计算需要大量的浮点数运算,常规计算非常耗时,可以考虑以下加速方法:

使用C++实现

C++和Python是两种流行的编程语言,在许多方面都有所不同。其中一个显著的差异是执行速度。一般来说,C++的执行速度比Python快得多。

使用SSE加速

SSE(Streaming SIMD Extensions)是一种由Intel提出的用于提升CPU运算速度的指令集。SSE提供了一组专门用于执行浮点运算的指令,可以用来加速向量运算、矩阵乘法以及内积运算等。

SSE提供了一组128位的浮点数寄存器,每个寄存器可以存储4个32位浮点数。SSE指令可以同时对4个数进行运算,因此可以大大提升运算速度。

使用GPU加速

使用GPU进行内积运算可以大大提升计算速度。GPU具有大量的浮点运算单元,可以同时执行大量的向量运算。

内积运算实践

C++ 内积运算

如下代码所示,我们分别定义两个函数,分别进行手动计算内积和使用SSE计算内积。smmintrin.h是一个C/C++头文件,包含了SSE4.1指令集的函数声明。

#include <smmintrin.h> 
#include <iostream>
#include <ctime>

// 手动计算内积
float inner_product(const float* x, const float* y, const long & len){
    float prod = 0.0f;
    long i;
    for (i=0;i<len;i++){
        prod+=x[i]*y[i];
    }
    return prod;
}

// SSE计算内积
float dot_product(const float* x, const float* y, const long & len){
    float prod = 0.0f;
    const int mask = 0xff;
    __m128 X, Y;
    float tmp;
 
 
    long i;
    for (i=0;i<len;i+=4){
        X=_mm_loadu_ps(x+i); //_mm_loadu_ps把float转为__m128
        Y=_mm_loadu_ps(y+i);
        _mm_storeu_ps(&tmp,_mm_dp_ps(X,Y,mask));
        prod += tmp;
    }
 
    return prod;
}

Go 内积运算

GO语言由Google开发,广泛应用于后端开发和大规模分布式系统的开发中。GO语言有许多优秀的特性,其中一个显著的优势是执行速度。

如下代码所示,我们实现了使用GO语言进行内积计算的逻辑:

import (
    "fmt"
    "time"
)
 
func InnerProduct(x []float32, y []float32) float32{
    var rect float32=0
    for i:=0;i<len(x);i++{
        rect+=x[i]*y[i]
    }
    return rect
}

Python 内积运算

Python是最常见的编程语言,接下来我们将手动完成向量内积运算。

array1=np.array(arr)
array2=np.array(brr)

for i in range(LEN):
    prod+=arr[i]*brr[i]

Numpy 内积运算

NumPy可以使用线性代数库,例如BLAS和LAPACK,加速向量运算、矩阵乘法和内积运算等。

array1=np.array(arr)
array2=np.array(brr)

prod=np.dot(array1,array2)

Jax 内积运算

Jax支持NumPy的大多数函数和API,可以方便地将NumPy代码转换为Jax代码。Jax也可以使用GPU加速计算,提升运算速度。

import jax
prod = jax.numpy.dot(array1, array2)

PyTorch 内积运算

在PyTorch中,可以使用Tensor类型进行向量运算。Tensor可以在CPU或者GPU上进行计算,在GPU上可以加速运算。

import torch
array1 = torch.from_numpy(array1)
array2 = torch.from_numpy(array2)

# CPU计算
prod = torch.dot(array1, array2)

# GPU计算
array1 = array1.cuda().float()
array2 = array2.cuda().float()
prod = torch.dot(array1, array2)

速度对比

如下我们将不同的工具在不同的向量维度下进行了速度的对比,这里我们都是运算需要的秒。

工具1w维度100w维度
C++2.4e-050.002279
C++ + SSE2.1e-050.001742
Go0.0000200.001098
Python0.0016370.156543
Numpy0.0002160.001519
Jax CPU0.0210190.004413
Pytorch GPU0.0007230.000690

从计算结果可以看出,C++和Go语言本身速度很快,SSE可以带来一定的加速。Python很慢,但Numpy很快。Numpy内置了向量和矩阵加速库,加速后和C++差不多。

Jax和Pytorch在CPU下速度差不多,但GPU加速很多,是所有工具中速度最快的。

 竞赛交流群 邀请函  #

△长按添加竞赛小助手
每天Kaggle算法竞赛、干货资讯汇总

与 28000+来自竞赛爱好者一起交流~

文章转载自Coggle数据科学,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论