1.Box2d源码阅读(2):从GJK到CCD
2.想要自学JAVA,重心指标重心应该如何入门?
3.3d稀疏卷积——spconv源码剖析(三)
Box2d源码阅读(2):从GJK到CCD
GJK算法在Box2D中的理论应用
Box2D中的GJK算法整合了Voronoi区域算法与重心坐标原理,旨在计算两个形状之间的源码最短距离。为了使查询更加通用,心理Box2D使用了封装的重心指标重心通用输入输出对象,通过b2distanceproxy来传递顶点和形状半径。理论通达信分时成交量源码当需要查询两个形状间的源码距离时,通过m_buffer进行特殊处理,心理以适应链状形状。重心指标重心
在GJK算法中,理论单纯形作为关键数据结构,源码其定义包含了索引信息以标识顶点来源于两个形状。心理在封装一层单纯形后,重心指标重心我们开始探索单纯形中的理论一些辅助函数,如solve2和solve3,源码这些函数用于更新单纯形的顶点。它们分别负责查找在已形成的线段或三角形上,距离原点直线距离最短的点。通过重心坐标方法计算a1和a2系数,求解p点在w1和w2之间的位置。
在两个形状之间距离求解过程中,函数通过一系列步骤实现。首先,定义了所需的公式和变量,利用p点与线段垂直的性质求解a1和a2系数。通过行列式方法求解方程组,得到p点在w1和w2之间的坐标。类似地,solve3函数也利用公式进行求解。
对于TOI(Time of Impact)的实现,Box2D通过三重for循环驱动来计算两个形状在运动过程中的撞击时间,以及快速运动中在一次tick内互相穿越的情况。首先,云协作平台源码使用sweep功能表示形状在指定时间后的location和rotation信息。接着,通过b2SeparationFunction查找两个形状之间的距离。在求解TOI时,函数通过三重循环结合二分法与割线法进行逼近,找到(t1, t2)范围内满足条件的时间。
尽管代码实现和示例存在细微差异,Box2D的GJK算法与TOI实现的核心逻辑保持一致,展示了通过优化查询和计算过程,高效地处理物理引擎中形状间的距离与碰撞检测问题。
想要自学JAVA,应该如何入门?
全面系统的Java内容如下:一、JavaSE基础篇
JavaSE就是一种标准版,是Java语言的基础部分,Java衍生出来的各种框架(如Spring系列)各种产品都是基于JavaSE标准,JavaSE是Java向上发展的基础,Java任何高级产品的底层基础都是JavaSE,通俗来讲这是所有孩子的”爹“。JavaSE如果学不好,理解不透彻,后面学习框架时就有如天书一般,所以JavaSE这部分的重要性是不言而喻的,希望各位初学者铭记。
主要包含内容:数据类型、基础语法、运算符、流程控制、数组、面向对象、常用类、异常处理、集合、html首页动画源码IO流、多线程、反射、注解、解析、网络编程。
PS:JavaSE的内容非常庞大,任何一套JavaSE教程都不会把所有的方法讲一遍,只会挑平时工作中常用的内容来讲解,所以JavaSE里面的内容很多都是课后自己在API文档中慢慢宽咐了解的,你自己一定要学会主动学习,不能坐以待毙。
推荐学习书籍:Java核心技术
二、数据库篇数据库是学习Java语言必学的一项内容,常见的数据库就是MySQL和Oracle这两种,作为初学者一般都是学习MySQL为主,一般情况下中小型企业都会选择MySQL数据库,比较大型的互联网公司会选择用Oracle,而学习Oracle相对于MySQL也要复杂一庆乎些,建议是主要学习MySQL数据库,Oracle作为了解即可。学习数据库较为简单,基本的操作就是增删改查。
三、Web开发Web前端内容:HTML/CSS/JavaScript/(前端页面)
注意:Java后端开发可以不用过多关注HTML页面及CSS的处理,但是最起码要会用简单的HTML,JavaScript是必须要会的,因为Javaweb后端程序员毕竟要接触使用AJAX方式处理数据及显示。当然如果只关注服务器端实现而不考虑任何用户界面,则HTML、CSS、JavaScript都不用关注,协同办公 源码下载但是完全脱离前端的开发现在虽然也不少,但是绝对不关心前端是不可能,尤其是JavaScript,但是前端却可以完全不关心服务器后台的任何实现。
推荐学习书籍:《JavaScript DOM编程艺术》(第二版)
四、高级框架1、Springframework 核心IOC容器
2、Spring boot 在Spring基础上的更全面提升效率的Spring工具
3、ORM 框架当今流行使用较多的是Mybatis 和 MP(Mybatis插件),Hibernate是可选性学习的
4、模板技术,比较成熟的Freemarker
5、Spring Cloud 微服务框架,Spring Cloud提供的全套的分布式系统解决方案。
五、工具maven 是构建管理项目的工具,svn 和git是团队协作开发的项目源代码及相关文档资料管理工具,需要学习者初步掌握其应用。
像Tomcat,jetty ,resin,JBoss,GlassFish 等都是部署运行Java web应用的服务器。
以上就是初学者大概学习的内容,我是尽量站在初学者的角度来说的,没有写得特别复杂,怕初学者看不懂,没有实质性的帮助。所以我尽量用白话把话说的简单一些,给大家罗列出主要学习的Java知识点。
Java学到什么程度才能达到就业的水平?不同的软件公司对研发人员的水平要求存在一定的差异,如果从大多数中小型企业来看能接受一个入职到本企业的de算法 python源码IT技术人员通常需要具备以下能力。
1 理解掌握Java核心面向对象的设计思想和代码构建,能以面向对象方式设计编写业务功能;
2 熟练掌握至少两种数据库的开发,如Oracle,mySql,能熟练编写基本常用及高级的SQL语句;
3 必需掌握并熟练应用Springframework IOC容器,深入了解IOC及AOP概念并应用,使用MVC实现对web 请求做出处理;
4 熟练掌握Java处理数据库的ORM框架myBatis,JDBCTemplate,对Hibernate也应有所了解;
5 熟练应用Spring 增强工具集合Spring boot;
6 至少熟练使用Eclipse及IDEA集成开发工具构建应用程序;
7 能够基本掌握MVN GIT Maven 在项目中的使用;
8 前端开发必需掌握JavaScript和常用的JS框架
以上这些都是中小型软件企业的入职基本要求,如果你能够达到这个水平,找到一份Java工作应该是不难的。
推荐的学习方式:系统视频教程+书籍辅助+有人指导视频教程:对于Java初学者来说,看视频学习也是最普通的方式,视频教程会把工作中常用的知识进行讲解,而且视频一般都是分章分节,每一个小节都只讲一个知识点,学习起来较为明确。但是视频教程尽量要完整,最好是一整套视频学习。
书籍辅助:书籍便于对理论知识的补充,以便更容易理解Java面向对象核心设计理念和代码实践功能。
PS:但是大部分人都没有耐心看不下去书,所以大部分人都是只看视频教程学习。如果自己能看的下去就看,看不下去就不看。
有人指导:大部分人都不可能全靠自己的能力把Java学的特别好,因为你不了解这个行业,也不知道怎么学,完全零基础自学Java想要找到工作,概率极低。所以建议如果真的想要做这行,尽量找人去带带你,有不懂的问题可以直接请教,少走弯路,提高效率。学习的质量决定以后工作的薪资以及起点,所以还是应该重视起来。
项目的重要性很多Java初学者看完一些视频,学过一段时间就说自己“会了”。这里我需要给大家纠正一个问题,希望每个学习Java的知友都能明确学习编程的中心是什么。
其实在我看来,学习编程从来都不存在会不会这样的说法。学习编程不同于初中学的数学、物理、化学,记住一些公式,做同样一种类型的习题,就证明类似的题型你会做了。
编程只讲技术能力是什么水平、什么级别的,最能证明技术水平处在什么阶段的,就是在做项目的过程中,研发好的互联网产品,写代码的质量怎么样,排错能力怎么样,找BUG的能力怎么样,构思功能模块整体布局的能力怎么样等等。
做作为初学者想要达到入门的水平,就是自己具备了一些简单项目的编码能力,初学者最重要的一点就是培养自己的编程思维,每一个程序都是不一样的,你不可能都背下来,学编程也不是靠死记硬背的,你只有能去独立编码写一些东西的时候,才有就业的机会。
所以做项目的能力才能去衡量一个学习的水平处在什么阶段,而往往那些嘴上说“会了”的人,往往没写过多少代码,也一个项目做不了出来,这就是纸上谈兵,完全曲解了学习编程到底在学什么,也不知道应该往哪里去。
所以一个Java初学者在学习的整体过程中,必须要有两个能拿得出手,能写在简历上的项目作为找工作的资本,并且要对于这两个项目的前前后后相当了解,才可能最后面试成功,一个初学者在学习完Java所有内容后,如若还达不到可以做简单项目的水平,那么他整个学习过程还是白费,没有达到最终的学习目的,就是学习质量不过关。所以项目的重要性希望大家都明确,因为有太多Java初学者不知道最后学习的目的是什么,最后白白的浪费时间。
学习心态:学习编程一定不是一个简单的事情,换句话说它还是挺困难的,毕竟能出去找到工作,就是少则五六千,多则上万的工种。这些知识都不是随随便便就是任何一个人都能学会的。关于这个学习心态,希望提示大家要把重心放到“学习”这件事上,因为我发现有很多Java初学者都是像“完成任务”一样去学习,所谓完成任务就是“我把这些视频看完就能找到工作吗”“我把这些都学完就能找到工作吗”学完并不等于“学会”,这是两种不同的概念。
你到底理没理解?
你到底能不能应用起来?
你到底用没用心?
你自己应该是最清楚的,我发现那些把学习当做完成任务一样去对待的,这样的人没有一个是有耐心的,自己在心里欺骗自己“把这些视频看完我就能找到工作”,到了最后自己就逐渐明白,完全是自欺欺人,最后放弃说自己不适合学这个。其实揭开这些人的面具真相就一个:他们没有耐心学习,也不喜欢学习,这是以前经历造成的,是多年的习惯导致的。
所以正确的学习心态一定是把关注点放到学习这件事本身,你要学会这些知识,这些内容,这些技术,这是需要一天一天逐渐积累起来的,并不是短时间就可以达到什么结果。
PS:如果你对于学习没什么耐心,没什么兴趣,我劝你不要来学习编程,学习编程绝对是一个耐心的活,也是需要不断学习和充电的行业。或者说已经到了信息时代,不爱学习的人,很难有耐心去学习知识的人,在信息时代是混不下去的,任何行业都是如此,不学习不进步不紧贴时代的人就一定会被淘汰。
最终自学Java能就业的人基本具备以下几点:1、有超强的学习耐心及进取心
2、手不懒,代码写的足够多,熟能生巧
3、有一定的学习能力,善于自学善于自己解决问题
4、可以独立写一些简单的项目
3d稀疏卷积——spconv源码剖析(三)
构建Rulebook
下面看ops.get_indice_pairs,位于:spconv/ops.py
构建Rulebook由ops.get_indice_pairs接口完成
get_indice_pairs函数具体实现:
主要就是完成了一些参数的校验和预处理。首先,对于3d普通稀疏卷积,根据输入shape大小,kernel size,stride等参数计算出输出输出shape,子流行稀疏卷积就不必计算了,输出shape和输入shape一样大小
准备好参数之后就进入最核心的get_indice_pairs函数。因为spconv通过torch.ops.load_library加载.so文件注册,所以这里通torch.ops.spconv.get_indice_pairs这种方式来调用该函数。
算子注册:在src/spconv/all.cc文件中通过Pytorch提供的OP Register(算子注册的方式)对底层c++ api进行了注册,可以python接口形式调用c++算子
同C++ extension方式一样,OP Register也是Pytorch提供的一种底层扩展算子注册的方式。注册的算子可以通过 torch.xxx或者 tensor.xxx的方式进行调用,该方式同样与pytorch源码解耦,增加和修改算子不需要重新编译pytorch源码。用该方式注册一个新的算子,流程非常简单:先编写C++相关的算子实现,然后通过pytorch底层的注册接口(torch::RegisterOperators),将该算子注册即可。
构建Rulebook实际通过python接口get_indice_pairs调用src/spconv/spconv_ops.cc文件种的getIndicePairs函数
代码位于:src/spconv/spconv_ops.cc
分析getIndicePairs直接将重心锁定在GPU逻辑部分,并且子流行3d稀疏卷积和正常3d稀疏卷积分开讨论,优先子流行3d稀疏卷积。
代码中最重要的3个变量分别为:indicePairs,indiceNum和gridOut,其建立过程如下:
indicePairs代表了稀疏卷积输入输出的映射规则,即Input Hash Table 和 Output Hash Table。这里分配理论最大的内存,它的shape为{ 2,kernelVolume,numAct},2表示输入和输出两个方向,kernelVolume为卷积核的volume size。例如一个3x3x3的卷积核,其volume size就是(3*3*3)。numAct表示输入有效(active)特征的数量。indiceNum用于保存卷积核每一个位置上的总的计算的次数,indiceNum对应中的count
代码中关于gpu建立rulebook调用create_submconv_indice_pair_cuda函数来完成,下面具体分析下create_submconv_indice_pair_cuda函数
子流线稀疏卷积
子流线稀疏卷积是调用create_submconv_indice_pair_cuda函数来构建rulebook
在create_submconv_indice_pair_cuda大可不必深究以下动态分发机制的运行原理。
直接将重心锁定在核函数:
prepareSubMGridKernel核函数中grid_size和block_size实则都是用的整形变量。其中block_size为tv::cuda::CUDA_NUM_THREADS,在include/tensorview/cuda_utils.h文件中定义,大小为。而grid_size大小通过tv::cuda::getBlocks(numActIn)计算得到,其中numActIn表示有效(active)输入数据的数量。
prepareSubMGridKernel作用:建立输出张量坐标(通过index表示)到输出序号之间的一张哈希表
见:include/spconv/indice.cu.h
这里计算index换了一种模板加递归的写法,看起来比较复杂而已。令:new_indicesIn = indicesIn.data(),可以推导得出index为:
ArrayIndexRowMajor位于include/tensorview/tensorview.h,其递归调用写法如下:
接着看核函数getSubMIndicePairsKernel3:
位于:include/spconv/indice.cu.h
看:
上述写法类似我们函数中常见的循环的写法,具体可以查看include/tensorview/kernel_utils.h
NumILP按默认值等于1的话,其stride也是gridDim.x*blockDim.x。索引最大值要小于该线程块的线程上限索引blockDim.x * gridDim.x,功能与下面代码类似:
参考: blog.csdn.net/ChuiGeDaQ...