减少重复造轮子,帮你解放生产力的「小矩阵功能」来啦!
时间:2022-10-27 22:55:46 阅读:103
Taichi语言中提供了很多好用的小矩阵库函数,方便大家在Taichi kernel中调用。这篇文章中将会给大家展示这些函数如何提高生产力而不降低性能。
同时这也是一篇呼吁大家提Feature Request的文章。期待大家提供更多你想要的小矩阵相关功能。欢迎在GitHub Discussion讨论贴中留言提“需求”,也欢迎感兴趣的社区同学和我们一起开发!点击“阅读原文”可以直达GitHub Discussion原贴。
有好奇心的各位朋友在自己的学习和工作生涯里,可能都或多或少的做过重复造轮子的事情,造轮子这件事的利弊不能一概而论。在学习某些技术的过程中,造轮子可能会帮助我们更深入的了解技术细节,提升我们的个人能力。当然也会有大佬青出于蓝,造出更厉害的轮子出来,从小木轮造成了跑车轮子。但在生产环境中,重复造轮子可能并不是个明智的选择。很多时候,我们自己写出来的代码并不能超越一些已有的开源库,因为这些库的实现需要深厚的背景知识和实践积累。
比如在工程领域,涉及很多数值计算相关的算法。数值计算中最关键的往往就是对矩阵、向量的操作以及线性系统的求解。
现实中,这样的线性系统往往还很大,有可能上百万个未知数。为了求解这些线性系统,科学家们开发了很多线性代数相关的数学库。比如:Intel基于自家CPU,充分利用其多核多线程并行能力推出的数学库:Intel(R)oneAPI Math Kernel Library;NVIDIA基于自家GPU并行能力推出的CUDA Toolkits,其中提供了cuBLAS,cuSparse,cuSolver等数学库。
很多时候,我们可以直接调用这些库来实现一些线性系统的求解,而不用担心这些库怎么实现多核/多线程并行的。这些库的开发者一般都有深厚的数学背景和工程能力,能够很好的基于硬件进行极致的优化。这时候我们要是再自己重复造轮子,恐怕只会费力不讨好。
那什么时候需要用户自己造轮子呢?一种情况是适配的库不好找。拿一个物理仿真的例子来说,在FEM弹性物体仿真中我们常常会使用SVD分解来判断计算单元是否翻转1。在CPU中,比较方便的办法是直接调用类似于Eigen这样的数学库。而在GPU中,可以在并行的核函数内被调用的SVD分解库就很难找了。
另一种情况是现有库的实现为了保证通用性而难以在所有的使用环境下都保证性能最优,所以在特定的环境下,用户会愿意手写更高效的实现。还是拿刚才的SVD分解举例,在限定了矩阵大小是的特定环境下,量身定制的方式可以极大加速这样的矩阵分解。所以A.McAdams,E.Sifakisd,J.Teran等人就专门针对矩阵写了一个基于CPU的SVD分解程序2。该算法能够把SVD分解从Computation Bound变成Memory Bound,极大的加速了计算效率。这也是Taichi中矩阵SVD分解的实现3。
在GPU的CUDA kernel中想要局部的调用矩阵的SVD分解函数,就只能老老实实自己手写了。但实现起来就更加麻烦了,写起来也很让人痛苦,还不一定正确。为此Kui Wu等人又针对GPU写了一个CUDA版本的矩阵的SVD分解,我们可以调用他们的实现⁴。但这样做同样有很多缺点:
1.需要根据不同的数据结构(SOA/AOS)来调用不同的SVD分解函数⁵。
#ifdef USE_SOA
svd3_SOA<<<pblks,threads>>>(d_input,d_answer,n);
#else
svd3_AOS_shared<<<pblks,threads>>>(d_input,d_answer,n);
#endif//USE_SOA
2.使用的时候代码冗长。
然而在Taichi里面,不管是使用CPU还是GPU作为计算硬件,调用一个矩阵的SVD分解只需要简单的如下几行代码:
ti.kernel
def test_svd():
A=ti.Matrix([[1,2,3],[4,5,6],[7,8,9]])
U,S,V=ti.svd(A)
Taichi统一函数接口,简化了用户的代码,提高了生产力
像SVD分解这种很高频的基础函数,如果每次自己手动去实现,还要考虑不同后端和不同数据结构产生的差异,那么很可能会出现各种bug,也会降低工作效率。而Taichi已经提供了小矩阵(和)相关的一些基础的操作,比如SVD分解,QR分解,线性方程组求解,特征值分解等常用的功能,而且你也不用担心不同后端,不同数据结构的不同实现问题。
Taichi在不同算法上相对CUDA的加速比,单位是百分比,计算方法为CUDA运行时间/Taichi运行时间。在每项测试中我们都会测试多种不同的算法参数,图中统计的加速比是全部结果的平均值。
除此之外,你可能也会担心性能问题。在这篇文章中👉🏻与CUDA相比,Taichi跑得快不快?我们基于多个算例(比如SVD,SAXPY)对比了Taichi和CUDA的性能。从对比中,我们可以看到Taichi在并行优化上能够充分发挥设备的计算性能。
我们相信,矩阵的SVD分解只是一大堆小规模,kernel内调用线性代数操作中的沧海一粟,平时大家自己一定还有不少写出老茧来的小规模函数。
欢迎大家把你在工程实现中常用到的一些小矩阵相关的操作,或者那些经常让你写到手软的CUDA kernel函数,在Github Discussion中(点击“阅读原文”即可访问)留言,也可以加入Slack的Taichi语言社区交流频道畅所欲言。
taichi期待大家多多提Feature Request,我们将逐步完善相关的功能,提供更多的工具,减少造轮子的烦恼,解放更多生产力!taichi https://taichi-lang.cn/
同时这也是一篇呼吁大家提Feature Request的文章。期待大家提供更多你想要的小矩阵相关功能。欢迎在GitHub Discussion讨论贴中留言提“需求”,也欢迎感兴趣的社区同学和我们一起开发!点击“阅读原文”可以直达GitHub Discussion原贴。
有好奇心的各位朋友在自己的学习和工作生涯里,可能都或多或少的做过重复造轮子的事情,造轮子这件事的利弊不能一概而论。在学习某些技术的过程中,造轮子可能会帮助我们更深入的了解技术细节,提升我们的个人能力。当然也会有大佬青出于蓝,造出更厉害的轮子出来,从小木轮造成了跑车轮子。但在生产环境中,重复造轮子可能并不是个明智的选择。很多时候,我们自己写出来的代码并不能超越一些已有的开源库,因为这些库的实现需要深厚的背景知识和实践积累。
比如在工程领域,涉及很多数值计算相关的算法。数值计算中最关键的往往就是对矩阵、向量的操作以及线性系统的求解。
现实中,这样的线性系统往往还很大,有可能上百万个未知数。为了求解这些线性系统,科学家们开发了很多线性代数相关的数学库。比如:Intel基于自家CPU,充分利用其多核多线程并行能力推出的数学库:Intel(R)oneAPI Math Kernel Library;NVIDIA基于自家GPU并行能力推出的CUDA Toolkits,其中提供了cuBLAS,cuSparse,cuSolver等数学库。
很多时候,我们可以直接调用这些库来实现一些线性系统的求解,而不用担心这些库怎么实现多核/多线程并行的。这些库的开发者一般都有深厚的数学背景和工程能力,能够很好的基于硬件进行极致的优化。这时候我们要是再自己重复造轮子,恐怕只会费力不讨好。
那什么时候需要用户自己造轮子呢?一种情况是适配的库不好找。拿一个物理仿真的例子来说,在FEM弹性物体仿真中我们常常会使用SVD分解来判断计算单元是否翻转1。在CPU中,比较方便的办法是直接调用类似于Eigen这样的数学库。而在GPU中,可以在并行的核函数内被调用的SVD分解库就很难找了。
另一种情况是现有库的实现为了保证通用性而难以在所有的使用环境下都保证性能最优,所以在特定的环境下,用户会愿意手写更高效的实现。还是拿刚才的SVD分解举例,在限定了矩阵大小是的特定环境下,量身定制的方式可以极大加速这样的矩阵分解。所以A.McAdams,E.Sifakisd,J.Teran等人就专门针对矩阵写了一个基于CPU的SVD分解程序2。该算法能够把SVD分解从Computation Bound变成Memory Bound,极大的加速了计算效率。这也是Taichi中矩阵SVD分解的实现3。
在GPU的CUDA kernel中想要局部的调用矩阵的SVD分解函数,就只能老老实实自己手写了。但实现起来就更加麻烦了,写起来也很让人痛苦,还不一定正确。为此Kui Wu等人又针对GPU写了一个CUDA版本的矩阵的SVD分解,我们可以调用他们的实现⁴。但这样做同样有很多缺点:
1.需要根据不同的数据结构(SOA/AOS)来调用不同的SVD分解函数⁵。
#ifdef USE_SOA
svd3_SOA<<<pblks,threads>>>(d_input,d_answer,n);
#else
svd3_AOS_shared<<<pblks,threads>>>(d_input,d_answer,n);
#endif//USE_SOA
2.使用的时候代码冗长。
然而在Taichi里面,不管是使用CPU还是GPU作为计算硬件,调用一个矩阵的SVD分解只需要简单的如下几行代码:
ti.kernel
def test_svd():
A=ti.Matrix([[1,2,3],[4,5,6],[7,8,9]])
U,S,V=ti.svd(A)
Taichi统一函数接口,简化了用户的代码,提高了生产力
像SVD分解这种很高频的基础函数,如果每次自己手动去实现,还要考虑不同后端和不同数据结构产生的差异,那么很可能会出现各种bug,也会降低工作效率。而Taichi已经提供了小矩阵(和)相关的一些基础的操作,比如SVD分解,QR分解,线性方程组求解,特征值分解等常用的功能,而且你也不用担心不同后端,不同数据结构的不同实现问题。
Taichi在不同算法上相对CUDA的加速比,单位是百分比,计算方法为CUDA运行时间/Taichi运行时间。在每项测试中我们都会测试多种不同的算法参数,图中统计的加速比是全部结果的平均值。
除此之外,你可能也会担心性能问题。在这篇文章中👉🏻与CUDA相比,Taichi跑得快不快?我们基于多个算例(比如SVD,SAXPY)对比了Taichi和CUDA的性能。从对比中,我们可以看到Taichi在并行优化上能够充分发挥设备的计算性能。
我们相信,矩阵的SVD分解只是一大堆小规模,kernel内调用线性代数操作中的沧海一粟,平时大家自己一定还有不少写出老茧来的小规模函数。
欢迎大家把你在工程实现中常用到的一些小矩阵相关的操作,或者那些经常让你写到手软的CUDA kernel函数,在Github Discussion中(点击“阅读原文”即可访问)留言,也可以加入Slack的Taichi语言社区交流频道畅所欲言。
taichi期待大家多多提Feature Request,我们将逐步完善相关的功能,提供更多的工具,减少造轮子的烦恼,解放更多生产力!taichi https://taichi-lang.cn/
郑重声明:文章内容来自互联网,纯属作者个人观点,仅供参考,并不代表本站立场 ,版权归原作者所有!
相关推荐