华为2020初赛思考(解决问题方法论,而非竞赛细致工作)

目录

1 问题定义

2 解决方案

2.1 算法和数据结构

2.2 性能优化(编译器能够有效优化已经转换成高效可执行代码源代码,重点参考深入理解计算机系统书籍第五章)

5.1 首先了解编译器的优化能力和局限性

5.2 表示程序性能

5.3 程序实例

5.4 消除循环的低效率

5.5 减少过程调用 过程中尽量不要较少函数调用,

5.6 消除不必要的内存引用。

5.7 理解现代处理器(有两个瓶颈,延迟界限和吞吐量界限)

     5.7.1 整体操作 了解现代处理器是如何进行操作,

     5.7.2 功能单元的性能 我们用延迟,发射时间,容量来表示功能单元的性能。

     5.7.3 处理器操作的抽象模型

5.8 循环展开

5.9 提高并行性

5.11 一些制约因素

    5.11.1 寄存器溢出

    5.11.2 分支预测和预测错误处罚

5.12 理解内存性能

     5.12.1 加载的性能

      5.12.3 存储的性能

3 理论分析

3.1 算法正确性证明

3.2 性能分析优化点理论方面

     1 深度优先搜索的复杂度分析是如何做到的?

          1.1 聚集分析是什么?

            1.2 记账方法没看


1 问题定义

有向图找环问题 有向图找出所有长度在3和7之内的环,其中需要包括共边环。

2 解决方案

2.1 算法和数据结构

 算法用深度优先遍历,数据结构用邻接表。

2.2 性能优化(编译器能够有效优化已经转换成高效可执行代码源代码,重点参考深入理解计算机系统书籍第五章)

引用深入理解计算机系统的话,分步骤进行

1 消除不必要的工作,包括函数调用,条件测试,内存引用

2 理解处理器执行模型,构建for循环的数据流程以及关键路径来决定一个循环执行周期的下界。,然后利用处理器提供的指令级并行能力,同时执行多条指令

5.1 首先了解编译器的优化能力和局限性

只进行安全的优化,必须假设不同指针可能会指向内存同一位置,叫做内存别名使用。这就限制了编译器优化的性能。 还有一种就是函数调用 如果贸然优化,会导致错误发生。可能考虑用内联函数来解决

5.2 表示程序性能

为什么用时钟周期来度量执行多少条指令?当我们关心输入数据n和运行多少周期之间的关系时。我们可以得到一组关于(x1,y1),(x2,y2),(x3,y3)的数,那么使用最小二乘拟合, 可以得到n和运行时间的关系。 这里面关于最小二乘拟合其实是多元微积分的知识,一旦涉及到函数,我们就有该函数定义域,连续,导数,极值等等。我学习多元函数求极值那一块知识,在分析这个二元函数微积分时,我们有定理 在对x导数=0,且对y导数=0,就可以获得极值。这是一个定理。在这列通过二阶偏导判断得到满足对x,对y导数为0的时候,是极小值,

''' 这里有疑问就是你如何知道是一次还是二次函数?可以通过画图看曲线走势, '''

5.3 程序实例

5.4 消除循环的低效率

代码移动(识别执行多次,但是计算结果不会发生变化的计算。),编译器会帮忙你做代码移动,但是有时候它没那么聪明,所以需要我们显式的做下代码移动工作,

5.5 减少过程调用 过程中尽量不要较少函数调用,

5.6 消除不必要的内存引用。

写出汇编代码(减少内存引用。) 然后改进之后,对比汇编代码看看。 临时变量就放在栈里面,访问很快。而用malloc或者new所申请的空间在堆上,在内存上,访问较慢。

5.7 理解现代处理器(有两个瓶颈,延迟界限和吞吐量界限)

延迟界限是限制指令级并行的能力瓶颈,而吞吐量界限刻画了处理器功能单元的原始计算能力。

     5.7.1 整体操作 了解现代处理器是如何进行操作,

包括两个大部分,指令控制单元和执行单元部分。指令控制单元不断取指令送到执行单元,但是分支处理不太一样。 指令从寄存器或者内存中取值,执行一个操作。并把结果存回寄存器或者内存中。这里面我们尽可能让结果放入寄存器中,这里应该有个图表示, ICU从指令高速缓存区读取指令,其中,指令译码把每一条指令切分多多条指令(放入先进先出队列),它一次可能读较多指令,然后发送到执行单元。每个时钟周期可能接受多条指令,分发到一组功能单元中, 这些功能单元专门用来处理不同类型的操作,比如算术运算,加载,存储,分支等。这也是neno技术的硬件支持,

     5.7.2 功能单元的性能 我们用延迟,发射时间,容量来表示功能单元的性能。

     5.7.3 处理器操作的抽象模型

这个是重点,这部分就是把你的代码抽象成数据模型,你可以清晰看到数据的动向,展示不同操作之间的数据相关是如何限制它们的执行顺序的。比如for循环执行过程中关键路径指的就是数据模型的主要矛盾,性能制约瓶颈就是关键路径的过程,这个过程你可以用计算器 的乘法,除法的延迟来近似效率。自然就可以近似得到最小二乘法的斜率了。 注意这种方法只能得到下界。 当然,它假设不关心循环的比较选择分支部分,只关心里面的数据流动。并且只关心这次迭代需要上次结果的关键路径流动。而不是全部计算,并不是循环中代码多就会执行慢的。

5.8 循环展开

第一可以减少条件分支,第二减少整个计算关键路径上的操作数量。它满足 k*的特质,其中k表示展开的k的倍数,m示几个分开的结果。比如2*2的展开,是可以有两条关键路径的。每条占n/2次。 循环展开就是并行处理啊,但是循环展开并不能破除性能制约瓶颈,只是减少循环次数。

5.9 提高并行性

但是m太多了不好,不能充分利用寄存器的性能。 利用多个累积变量保存结果,最后再一次性算出 但可能出现每个累计变量那部分数据不太一样,出现每个累积变量数据分布不一,那得不偿失。所以这个提高并行性是假定所有分块数据的分布是一样的。

5.11 一些制约因素

关键路径指明了执行该程序所需时间的一个基本下界。如果有关键路径,那么关键路径的所有延迟之和等于T,那么这个cheng'xu

    5.11.1 寄存器溢出

循环展开也是有限度的,如果并行计算的容量超过了寄存器,就会溢出。那么计算机就会把那些溢出的变量放在堆栈上,

    5.11.2 分支预测和预测错误处罚

用条件转移代替数据分布不一的分支预测好些。 不要过分关心可预测分支,这取决于数据的分布相同吗?

5.12 理解内存性能

(注意这跟上面的数据流图不太一样,上面关心的是数据量较少的运算,下面关心的是数据量大这个特点。那自然就设计到加载和存储的性能,这一部分也可以画数据流程图)

     5.12.1 加载的性能

就是在循环中,某些值得确定必须要上行代码得结果才可以继续执行,这样就只能依赖,会比较慢,而不依赖上行结果的,可以并行,快些。 这部分也会加入关键路径之中,是因为它的加载和存储不依赖于循环的条件判断,自然跟前面的数据流向是一样的,也是关键路径。

      5.12.3 存储的性能

 

 

3 理论分析

3.1 算法正确性证明

没有提供证明,建议参看算法导论关于算法正确性证明那一块。

 

3.2 性能分析优化点理论方面

     1 深度优先搜索的复杂度分析是如何做到的?

使用聚集分析技术,它是平摊分析的一种,平摊分析主要包括三种。聚集分析,记账昂发,势能方法。

          1.1 聚集分析是什么?

   在聚集分析中,要证明对所有的n,由n个操作所构成的序列的总时间在最坏情况下为T(n)。平摊分析(Amortized Analysis)将数据结构的不同操作放到一起来考虑,而不是仅对某种操作的单一考虑。在平摊分析中,不会涉及概率问题。 平摊分析可以用来证明,在一系列操作中,即使某个操作代价很大,但平均代价仍是很小的。''' 请深刻理解平摊分析对某一个数据结构的操作总次数考虑 ,其中典型就是DFS和BFS用邻接链表时时间复杂度分析。 ''' ''' 那么借助聚集分析,我们可以得到我们算法的时间复杂度在O(v(avg(drgredd)的3次方-1)) 到 O(v(avg(drgredd)的7次方-1))之间 '''

            1.2 记账方法没看

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值