精华内容
下载资源
问答
  • 首先研究了LU分解算法,然后讨论了传统粒子群优化算法并针对用于循环分块方面的不足加以改进,最后把优化的粒子群优化算法用于LU分解算法之中,从而提出了一个PSO-LU循环分块算法。仿真实验结果表明,和原始基准测试程序...
  • JavaScript性能优化——循环优化

    千次阅读 2019-05-18 16:22:24
    循环是我们在写代码时经常用到的一种结构,而往往在考虑性能优化时,循环优化能带来很大的收益,特别是当我们不得不循环多次时,如果没对性能进行优化,那毫无疑问会带来性能的负担。 循环的类型 1.for循环 for...

    循环是我们在写代码时经常用到的一种结构,而往往在考虑性能优化时,循环的优化能带来很大的收益,特别是当我们不得不循环多次时,如果没对性能进行优化,那毫无疑问会带来性能的负担。

    循环的类型


    1.for循环

    for循环可能是我们最常用的循环,相对于其他种循环来说,for循环将初始化,判断终止条件,判断值的改变明显地写在了括号内,更为直观。

    for(var i=0;i<sum;i++){
        //...
    }

    2.while循环

    var i=0;
    while(i<sum){
        // ...
        i++;
    }

    3.do...while循环

    var i=0;
    do{
        // ...
        i++;
    }while(i<sum)

    4.for-in

    for-in循环一般用于遍历对象中的key,一般不会使用for-in,因为for-in循环会对性能有更多消耗,会在下文提及原因

    for(var prop in object){
        // ...
    }

    5.for-of

    for-of循环也可用于一个有Iterator的对象,如数组,具体可见ES6学习笔记(六)Iterator接口,与for-in不同的是,for-of可以使用break和return语句来跳出循环。然而,虽然其性能消耗比for-in少,但是其性能消耗相对于前三种来说还是更多的,将在下文提及原因

    for(var val of arr){
        // ...
    }

    循环类型的性能


    在对上面的几种循环遍历数组进行测试后,可以发现for-in循环和for-of循环的速度明显慢于其它三种,对于for-in来说,需要同时遍历实例和原型链,在遍历上的消耗更多,而对于for-of来说,需要去调用Symbol.iterator函数来构建一个迭代器,自动调用next(),且不向next()传入任何值,在接收到done:true之后停止,自然回比前三种方法慢。

    (这里的性能测试我使用了console.time()和console.timeEnd()之间的时间差距来比对,因为会受浏览器等各种因素影响,上面的结论是我测试了多组数据后得出的结论)

    let arr = [];
    arr.length = 10000;
    arr.fill(1);
    
    (function() {
        console.time('for循环');
        for (var i = 0; i < arr.length; i++) {
            // ... 相同操作
        }
        console.timeEnd('for循环')
    })();
    
    (function() {
        console.time('while循环')
        var i = 0;
        while (i < arr.length) {
            // ...相同操作
            i++;
        }
        console.timeEnd('while循环')
    })();
    
    (function() {
        console.time('do-while');
        var i = 0;
        do {
            // ...相同操作
            i++;
        } while (i < arr.length)
        console.timeEnd('do-while');
    })();
    
    (function() {
        console.time('for-in');
        for (var i of arr) {
            // ...相同操作
        }
        console.timeEnd('for-in');
    })();
    
    (function() {
        console.time('for-of');
        for (var i of arr) {
            // ...相同操作
        }
        console.timeEnd('for-of');
    })();

    下面是其中一次的执行结果

    性能优化


    要对循环的性能进行优化,只能减少其每次循环的工作量,或者减少循环的次数

    减少每次循环工作量

    首先看看for遍历一个数组每次循环的工作量

    for(var i=0;i<arr.length;i++){
        //...操作
    }

    1.查找一次arr的长度

    2.比较一次i和arr.length的值

    3.判断比较结果为true或false

    4.执行for循环内的自增

    5.i变量的自增(如果步骤3中判断结果为true的话)

    存储arr.length的值

    每次我们都要去查找一次length的值,那么我们为什么不先在设置初始条件时使用一个变量来存储arr的length值呢。

    for(var i=0,len=arr.length;i<len;i++){
        //...操作
    }

    这样做的好处是,arr至少是在当前作用域链的下一个位置,如果我们把arr.length放在当前一个局部变量中,在查找该值时在作用域链上查找的步数就会减少,所以能有效地减少性能的消耗。这样上面的步骤就变为

    1.比较一次i和len的值

    2.判断比较结果为true或false

    3.执行for循环内的自增

    4.i变量的自增(如果步骤3中判断结果为true的话)

    倒序循环

    倒序循环是一种通用的循环优化方法,我们通过代码来理解

    for(var i=arr.length;i--;){
        //...操作
    }

    此时每次循环的步骤变为

    1.i==true的判断(i为0时等式即成立)

    2.i变量的自减

    3.执行循环内的操作

    可以看到,倒序操作实际上就是将i和数组长度的比较和判断为true或false这两步合并,以此来得到性能上的优化。

    减少循环次数

    达夫设备

    达夫设备实际上就是在一次循环中完成多次循环的事情,以达到减少循环次数的作用,看看下面的代码(代码源自《高性能JavaScript》)

    // items为要遍历的数组,process为对数组内成员的操作方法
    
    var i=items.length%8;
    while(i){
        process(items[i--]);
    }
    
    i=Math.floor(items.length/8);
    
    while(i){
        process(items[i--]);
        process(items[i--]);
        process(items[i--]);
        process(items[i--]);
        process(items[i--]);
        process(items[i--]);
        process(items[i--]);
        process(items[i--]);
    }

    这里通过取长度除以8的余数,先进行这个余数次数的循环,然后之后每次循环执行8次自减操作,相当于一次循环中完成八次循环的操作,以此来达到减少循环的次数的目的

    基于函数的迭代


    很多框架中都封装了迭代循环的方法,包括JavaScript本身也有原生的数组迭代方法,看看下列实例(代码原则《高性能JavaScript》)

    // 原生数组方法
    items.forEach(function(value, index, array) {
        process(value);
    });
    
    // YUI 3
    Y.Array.each(item, function(value, index, array) {
        process(value);
    });
    
    // jQuery
    jQuery.each(items, function(index, value) {
        process(value);
    });
    
    // Dojo
    dojo.forEach(items, function(value, index, array) {
        process(values);
    });
    
    // prototype
    items.each(function(value, index) {
        process(value);
    });
    
    // MooTools
    $each(items, function(value, index) {
        process(value);
    });

    虽然函数迭代的方法较为方便,但从性能上来说,函数迭代需要去调用函数,性能上的消耗会比普通的循环更多,所以在追求性能的情况下不适合使用函数迭代的方法。


    参考自《高性能JavaScript》

    展开全文
  • 为了进行循环优化,首先需要确定的是程序流图中哪些基本块构成一个循环。按照结构程序设计思想,程序员在编程时应使用高级语言所提供的结构性的循环语句来编写循环。而由高级语言的循环语句所形成的循环,是不难找出...

    循环优化概述.

    什么叫做循环?循环就是程序中那些可能反复执行的代码序列。也正是由于这部分代码序列可能会被反复执行,所以在进行中间代码优化时应着重考虑循环优化,这对提高目标代码的效率起到很大的作用。为了进行循环优化,首先需要确定的是程序流图中哪些基本块构成一个循环。按照结构程序设计思想,程序员在编程时应使用高级语言所提供的结构性的循环语句来编写循环。而由高级语言的循环语句所形成的循环,是不难找出的。对于循环中的代码,可以实行代码外提、强度削弱和删除归纳变量等优化操作。一个中间代码序列的程序流图如下所示:
    在这里插入图片描述
    我们不难看出,其中B 2 _2 2和B 3 _3 3分别构成一个循环,{B 2 _2 2,B 3 _3 3,B 4 _4 4,B 5 _5 5}构成一个范围更大的循环。而我们要进行循环优化,首先需要知道循环在哪里,接下来,我们就一步步给出,整个循环优化的过程。

    计算必经节点集.

    【定义】:若从首结点出发到达结点N j _j j的每一条通路都必须经过结点N i _i i,那么我们称N i _i i是N j _j j的必经节点,记为N i _i i dom N j _j j,其中dom是dominate的简写。那么N j _j j所有必经节点的集合,就是N j _j j的必经节点集,记为D(N j _j j).

    计算程序流图中必经节点集的算法也是一个不动点算法,通过每一次的迭代来计算一个结点的必经节点集。当程序流图中所有结点的迭代计算结果都不发生改变时,说明已经获得了最终的结果,算法宣布结束。下面我们给出计算必经节点集的算法:
    在这里插入图片描述
    这里我们也给出一个例题,作为计算必经节点集算法的收尾:

    【下图引用自中南大学徐德智老师的编译原理2020年授课PPT】

    在这里插入图片描述
    需要注意的是,该算法并不像图中那样,一次迭代计算就可以确定结果,而是需要再一次迭代确认了所有的结点都没有发生变化,才能确定最终结果的。

    循环查找算法.

    1.查找回边.

    【定义】如果一个程序流图中存在有向边<N i _i i→N j _j j>,并且N j _j j∈D(N i _i i),那么我们称有向边<N i _i i→N j _j j>是一条回边。

    依旧是我们前一部分给出的实例,考察其中的回边:

    【下图引用自中南大学徐德智老师的编译原理2020年授课PPT】

    在这里插入图片描述

    2.查找循环.

    求出了程序流图中的回边之后,我们就可以基于回边来查找循环。具体的方法是,若<N i _i i→N j _j j>是一条回边,那么该回边构成的循环中的结点包括:N i _i i和N j _j j以及所有不经过N i _i i能够到达N j _j j的结点。我们以上图中求出的三条回边为例,6→6确定的循环中只包括结点6;7→4确定的循环中包括结点有{4,7,5,6};4→2确定的循环中包括的结点有{2,4,3,5,6,7}。

    【下图引用自中南大学徐德智老师的编译原理2020年授课PPT】

    在这里插入图片描述

    代码外提.

    至此我们已经完成了查找循环包含结点的工作,接下来就是要对循环体中的中间代码进行优化了。循环中的某些代码虽然随着循环反复地执行,但其中某些运算的结果并没有发生改变,例如循环中有形如A:=B op C的代码,并且如果B和C都是常数,或者到达它们的定值点都在循环外,那么不管循环多少次,每次计算出来得到的B op C的结果都是不变的,对于这样的不变运算,我们完全可以将其外提到循环以外,避免其随着循环多次计算。如此一来,程序的结果没有发生变化,但程序的运行速率却得到了一定程度的提高,这就是代码外提。

    【定义】所谓变量A在程序中某一点d的定值到达了另一点u,或者说变量A的定值点d达到另一点u,指的是程序流图中从d有一条通路到达u,并且通路上没有A的其它定值点。

    实行代码外提时,我们在循环的入口结点之前建立一个新结点(基本块),称为循环的前置结点,该前置结点以循环的入口结点为其唯一后继。并且原来流图中从循环外引到循环入口结点的有向边,都改为引到该前置结点。如下图所示:
    在这里插入图片描述
    我们考虑的循环结构,其入口结点都是唯一的,从而其前置结点也是唯一的,我们后续进行代码外提时所有外提的代码都将提到前置结点中。下面一段Pascal源程序,是我们叙述代码外提的第一个例子:

    for I:=1 to 10 do
    	A[I,2*J]:=A[I,2*J]+1
    

    它对应的中间代码序列如下:

    【下图引用自中南大学徐德智老师的编译原理2020年授课PPT】

    在这里插入图片描述

    1. 考察序号为3和7的语句,因为循环中并没有J的定值点,所以其中J所有引用的定值点都在循环外,从而3和7都是循环不变运算;
    2. 考察序号为6和10的语句,分配给数组A的首地址addr(A)的值并不会随着循环的一次次执行而改变,所以6和10也都是循环不变运算。

    所以我们可以做出这样的判断:3与7、6与10都可以外提到该循环的前置节点中,进行了代码外提之后的中间代码序列如下所示:

    【下图引用自中南大学徐德智老师的编译原理2020年授课PPT】

    在这里插入图片描述
    那么问题又来了,是不是在任何情况下,都可以将循环不变运算进行外提呢?我们看第二个例子:
    在这里插入图片描述
    从程序流图中我们不难看出,{B 2 _2 2,B 3 _3 3,B 4 _4 4}构成了一个循环,并且B 2 _2 2是入口结点,B 4 _4 4是出口结点。

    【定义】出口结点是指循环中具有如下性质的结点:从该结点有一条有向边引到循环外的某结点。

    图中我们也不难看出,基本块B 3 _3 3中的I:=2语句是循环不变语句,那么我们是否可以直接将这一语句外提到循环以外的前置结点B 2 ′ _2' 2呢?我们暂且认为可以这样做,外提之后的程序流图如下所示:
    在这里插入图片描述
    我们看外提了I:=2这一语句的程序流图,执行到基本块B 5 _5 5时,变量I的值总会是2,从而J的值也会是2.但我们需要注意的是,在原始的、没有进行I:=2外提的程序流图中,B 3 _3 3并不是B 4 _4 4的必经结点。我们在原始流图中考虑X=30、Y=25的情况,这样的情况下B 3 _3 3是不会被执行的,所以执行到B 5 _5 5时变量I的值应该是1,从而J的值也应该是1而非2.那么很显然,我们进行了I:=2外提的程序已经改变了程序运行的结果,这必然是不允许的。问题到底出在什么地方呢?其实前面已经点出,B 3 _3 3并不是循环出口结点B 4 _4 4的必经节点,再直白一点说,B 3 _3 3中的代码并不一定会对B 4 _4 4中的代码起到作用,但如果我们将其外提到循环的前置结点,那么该外提的语句必然是会对B 4 _4 4产生影响的,这就导致了程序运行结果被改变的风险,我们并不允许这样的风险存在。
    所以从这个例子中我们可以看到,当一个循环不变运算要外提到循环的前置结点时,要求该循环不变运算的语句所在的结点是循环的所有出口结点的必经结点
    另外,我们注意到,如果循环中变量I的所有引用点都是B 3 _3 3I的定值点所能到达的,I在循环中不再有其它的定值点,并且出循环之后也不会再引用变量I的值(即在循环外的循环后继结点入口,变量I不是活跃的),那么即使B 3 _3 3不是B 4 _4 4的必经结点,还是可以将I:=2外提到循环的前置结点,因为这样做并不会改变程序的结果。
    再一个例子,如果我们将上述程序流图中的基本块B 2 _2 2改为:

    I:=3
    if X<Y goto B3
    

    考虑B 2 _2 2I:=3外提的问题。
    通过计算必经结点集可以发现,B 2 _2 2确实是循环出口结点B 4 _4 4的必经结点,那么我们是否可以将I:=3进行代码外提呢?同样的论述过程,我们姑且认为可以,那么如果程序的执行过程是2-3-4-2-4-5,则执行B 5 _5 5时的变量I值为2,从而J的值也是2;而如果不进行外提操作,那么同样的执行过程下,I和J的值都应该是3,而非2.这一错误的原因在于,循环中除了B 2 _2 2以外,B 3 _3 3也对同一个变量进行了定值。
    所以从这个例子中我们可以看到,当我们将循环不变运算A:=B op C外提时,要求循环中的其它地方不再有A的定值点
    第三个例子,也是最后一个例子,我们看下面一个程序流图:
    在这里插入图片描述
    考察基本块B 4 _4 4中循环不变运算I:=2这一语句的外提操作。首先,B 4 _4 4结点就是整个循环的出口结点,并且B 4 _4 4结点也是其本身的必经结点;其次整个循环{B 2 _2 2,B 3 _3 3,B 4 _4 4}中也没有第二个对于变量I定值的语句。那么我们是否可以将这一语句外提呢?同样的方法,我们还是暂且认为这一语句可以外提,再比较对于同一个执行过程,外提前后的执行结果。我们考虑X=0、Y=2的情况,循环的执行流程是2-3-4-2-4-5,代码外提前,程序的执行结果为J=2;而代码外提后,程序的执行结果为J=3.
    通过这个例子,我们看到,当将循环不变语句A:=B op C进行代码外提时,要求循环中所有对于A的引用点都是并且仅仅是这一定值语句所能到达的。上述的例子中,能够到达A:=I+1这一对于I的引用的定值语句,不仅有B 4 _4 4中的I:=2,还有B 1 _1 1中的I:=1.
    最后我们给出查找循环L中不变运算的算法:
    在这里插入图片描述
    以及代码外提算法:
    在这里插入图片描述

    强度削弱.

    我们要介绍的第二种循环优化技术叫做强度削弱。强度削弱是将程序中执行时间较长的运算替换为执行时间较短的运算。例如,最常见的就是将循环中的乘法运算用递归的加法运算来代替。我们考察前面经过了代码外提的示例流图:

    【下图引用自中南大学徐德智老师的编译原理2020年授课PPT】

    在这里插入图片描述
    不难看出{B 2 _2 2,B 5 _5 5}是一个循环,并且B 2 _2 2是循环的入口结点。我们注意序号为13的语句,这里的变量I是一个递归赋值的变量,每循环一次,它增加一个常量1。另外,序号为4和8的语句在计算T 2 _2 2和T 6 _6 6时,都会使用I的值,并且T 2 _2 2和T 6 _6 6都是I的线性函数,每循环一次,它们都增加一个常量10.因此,如果把4和8外提到循环的前置结点中,并且在13号语句之后添加上为T 2 _2 2和T 6 _6 6增加常量10的语句,程序的运行结果依然不变。

    【下图引用自中南大学徐德智老师的编译原理2020年授课PPT】

    在这里插入图片描述
    经过上述变换,循环中原来的乘法运算4和8被替换为了在前置结点中进行一次初始化的乘法运算(计算初值)以及在循环中递归赋值的加法运算(4’)和(8’).不仅加法运算一般来说比乘法运算快,而且这种在循环前计算初值,再于循环末尾进行常量递增的运算,可以利用变址器提高运算速度,从而使运算的强度得到削弱。所以我们称这种优化技术为强度削弱。
    强度削弱不仅对于乘法可以实行,对于加法也可以实行。例如上图中序号为5和9的语句,T 3 _3 3与T 7 _7 7的计算中引用到了T 2 _2 2和T 6 _6 6,并且T 2 _2 2和T 6 _6 6也是递归赋值的变量,每循环一次,它们的值就增加一个常量10.而T 3 _3 3与T 7 _7 7的另一个运算对象都是循环不变量,所以每循环一次,T 3 _3 3与T 7 _7 7的值就增加一个常量10.很自然地,我们会想到对它们进行强度削弱,即外提一个初始化语句,在循环的末尾添加常量递增语句,得到的优化结果如下所示:

    【下图引用自中南大学徐德智老师的编译原理2020年授课PPT】

    在这里插入图片描述
    从上面的例子中我们可以看到:

    1. 如果循环中有A的递归赋值A:=A±b 1 _1 1,并且循环中另一个变量B的赋值运算可以写为B:=k*A±b 2 _2 2的形式,那么对于B的赋值运算,我们可以进行强度削弱;
    2. 进行强度削弱之后,循环中可能会出现一些新的无用赋值,例如上图中的(4’)和(8’),因为循环中不再使用T 2 _2 2和T 6 _6 6,那么如果循环出口之后它们也不是活跃变量,是完全可以删除的;
    3. 循环中下标变量的地址计算是相当耗费时间的,这里介绍的方法对削弱下标变量地址计算的强度是非常有效的。前面的例子中,数组是二维的,如果我们考察一个更高维度的数组,将会进一步看到强度削弱的作用。对于下标变量地址计算来说,强度削弱实际上就是实现下标变量地址的递归计算。

    删除归纳变量.

    我们要介绍的最后一种循环赋值技术叫做删除归纳变量。讲述具体的流程之前,首先给出基本归纳变量以及归纳变量的定义:

    【定义】基本归纳变量:循环中对于变量A的赋值只有唯一的、形如A:=A±b 1 _1 1的赋值,那么称A为循环中的基本归纳变量;
    【定义】归纳变量:如果A是一个基本归纳变量,循环中对于B的赋值总是可以化归为A的同一个线性函数,即B:=k*A±b 2 _2 2,那么我们称B是一个归纳变量。

    考察进行了代码外提之后的示例程序流图:

    【下图引用自中南大学徐德智老师的编译原理2020年授课PPT】

    在这里插入图片描述
    不难发现变量I是循环{B 2 _2 2,B 3 _3 3}的基本归纳变量,T 2 _2 2和T 6 _6 6是循环中与I同族的归纳变量,再继续发掘,T 3 _3 3和T 7 _7 7也是与I同族的归纳变量。
    一个基本归纳变量除了用于自身的递归赋值以外,往往只在循环中用于计算其他的归纳变量和控制循环的进行。经过了强度削弱之后的示例程序流图如下所示:

    【下图引用自中南大学徐德智老师的编译原理2020年授课PPT】

    在这里插入图片描述
    关注基本块B 3 _3 3可以发现变量I除了用于自身的递归赋值以外,只用于控制循环的进行。这时,我们可以使用与I同族的某一个归纳变量来代替I控制循环的进行,从而删除变量I.例如,我们选取T 3 _3 3(T 7 _7 7与T 3 _3 3都在循环中被引用,所以是一样的,而T 2 _2 2和T 6 _6 6在循环中没有被引用)来代替I, 由于T 3 _3 3可以写为10*I+T1,并且循环的控制条件为I>10,所以用T 3 _3 3代替了I之后,控制条件变为了T3>100+T1.为了不在每一次进行判断时都计算100+T 1 _1 1的值,我们引入新的临时变量R:=100+T 1 _1 1,所以序号为2的if语句改写为:

    R:=100+T1
    if T3>R goto (15)
    

    然后我们就可以删去变量I了,这一优化技术称为删除归纳变量,也叫变换循环控制条件。如果我们假定T 2 _2 2和T 6 _6 6在循环出口之后也不是活跃的,那么我们完全可以删去这两个临时变量(因为它们在循环中也没有被使用)。但如果我们在选择代替I的变量时选择了T 2 _2 2或T 6 _6 6,那么(4’)或(8’)就不能删除了,最后完成删除归纳变量的中间代码如下:

    【下图引用自中南大学徐德智老师的编译原理2020年授课PPT】

    在这里插入图片描述
    删除归纳变量是在强度削弱之后进行的。我们在下面统一给出强度削弱和删除归纳变量的算法:
    在这里插入图片描述

    展开全文
  • for循环优化的基本概念、对for循环施行流水的优化、for循环的展开以及for循环的循环变量的数据类型是否对结果资源有影响 1. 流水线优化 2. for循环的展开 默认情况下for循环是被折叠的,所谓折叠可以理解...

    一. 基本性能指标

    for循环优化的基本概念、对for循环施行流水的优化、for循环的展开以及for循环的循环变量的数据类型是否对结果资源有影响
    在这里插入图片描述

    1. 流水线优化

    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

    2. for循环的展开

    在这里插入图片描述在这里插入图片描述在这里插入图片描述

    • 默认情况下for循环是被折叠的,所谓折叠可以理解为所有每次循环都是采用同一套电路,只是这个电路被分时复用,而展开就意味着这个for循环被复制了n或者n/2份,这个是可以设置的;
    • for循环可以部分展开,比如trip count为6时,可以将for循环拆分成3个,分别对应(0,3)、(1,4)、(2,5)次循环,其中同组的共用一套逻辑资源;

    3. 循环变量i

    在这里插入图片描述
    正常情况下,循环变量i的类型不会影响最后的综合结果,因为Vivado HLS考虑的是i的最大值,然后使用FPGA的最小资源

    4. 总结

    在这里插入图片描述

    二. for循环优化——循环合并

    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

    • 两个相互独立的for循环我们期望可以并行执行,但是在默认情况下,HLS是顺序执行的,我们可以在HLS中通过directive来将两个for循环合并;
    • 合并可以帮助我们在一定程度上降低latency,这是因为在默认情况下for循环都会创建额外的状态机,而状态机会占用额外的时钟周期和资源;
    • 当循环边界不一致时,以较大的那个作为合并后的循环边界;
    • 如果一个循环变量是边界,而另一个是变量,这个时候不能合并,会报错;
    • 如果两个循环边界都是变量,同样合并时会报错;

    对于变量作为边界的for循环如何合并?
    在这里插入图片描述在这里插入图片描述
    合并的规则:
    在这里插入图片描述

    • 循环边界都是常数且不一致时,合并后的循环边界由较大的边界决定;
    • 边界都是变量时,要求两个变量能够达到的最大值是一致的,这保证了它们有相同的迭代周期;

    总结:
    在这里插入图片描述

    三. for循环的优化——数据流

    循环之间有依赖关系,可以应用流水线,不可以用合并;
    在这里插入图片描述
    没有应用数据流时循环执行顺序为左,应用了之后为右,可以看出来,使用了数据流之后我们并不需要前面的循环完全执行结束后才执行下一个循环任务,只有前面的有输出我就可以做下一个子任务了。同时各个任务之间有交叠,这帮助我们降低latency进而提高数据吞吐率。
    在这里插入图片描述在这里插入图片描述
    dataflow优化的限制:
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

    • single-producer-consumer Model,两个循环同时使用前面的同一个变量,不能应用数据流,改善的方法是在前面将这个变量分别赋给不同的两个变量,进而这两个变量分别进入不同的循环;
    • Bypassing Tasks Model,temp3的数据来自loop2,所以不能使用合并和dataflow,改善的方法是在中间循环中通过简单的复制消除bypass;
    • Configuring Dataflow Memory Channels,HLS实现不同任务之间的channels是通过ping-pong或者FIFO缓冲器;如果参数类型为scalar、pointer、reference,HLS会将其综合成FIFO,如果是个数组,HLS判断出数据流是顺序的就会配置成FIFO,否则就是ping-pong RAM;
    • 也可以使用cofig_dataflow configuration显式地告诉HLS要配置成FIFO还是ping-pong RAM,配置成FIFO时要特别注意FIFO的深度,否则在C和RTL协同仿真时会报错;

    总结:
    在这里插入图片描述

    四. for循环优化——嵌套的for循环

    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
    三种类型的嵌套for循环:

    • Perfect loop nest:循环的边界都是常量,同时循环体只会在最内层的for循环中出现;
    • Semi-Perfect loop nest:最外层循环的边界是变量,但是最内层for循环边界是常数,同时循环体一定在最内层for循环;
    • Imperfect loop nest有两种,一种是循环边界都是常量,但是外部循环也有循环体,第二种是虽然外部循环没有循环体,但是内部循环的边界是变量;

    对于Imperfect loop,我们希望通过一些手段将其转化成Perfect或者Semi-Perfect loop。
    在这里插入图片描述
    对某层for循环做流水,该层下面的for循环都会被展开;

    不加任何约束、对最内部做流水、中间层做流水、最外部做流水的比较:显然对最外部做流水的延迟最小,但对应的增加了硬件成本;同时对整个函数做流水会将所有层都展开,延迟最低,硬件成本最高。
    在这里插入图片描述在这里插入图片描述
    矩阵乘法优化:
    在这里插入图片描述在这里插入图片描述
    总结:
    在这里插入图片描述

    五. for循环优化的其他方法

    在这里插入图片描述

    1. 并行化的问题

    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

    2. Loop Pipeline with Rewind Option

    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
    rewind并不是适合所有for循环,它是有条件的。

    什么时候使用Pipeline会失效?
    当将一个任务做流水时,for循环下面的操作都会被展开,如果for循环边界是变量时,这个操作就会失败;
    在这里插入图片描述

    3. 如何处理循环边界是变量的情形?

    当循环边界是变量时,HLS无法确定loop的latency,进而无法确定整个函数的latency。
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
    对于这种情形有三种解决方法:

    • 使用Tripcont这种directive,这种方法不会对综合结果有任何影响,只是用于report的显示以及不同solution之间的比较;
    • 将循环边界的数据类型声明为 ap_int,对综合结果有优化;
    • 在C代码中使用assert macro;

    三种方法的比较:可以看出来,使用assert的方式latency最小,硬件成本也最低。
    在这里插入图片描述
    总结:
    在这里插入图片描述

    展开全文
  • 这是一个简单的循环嵌套决问题,常最规的思路是用三层循环来枚举寻找符合条件的 公鸡、母鸡、小鸡的数量,代码如下(输出结果在文章最后): C++; #include &lt;iostream&gt; using namespace std; int main...

    百钱买百鸡,一百块钱,买一百只鸡,公鸡一只五元,母鸡一只三元,小鸡一元三只,求应各买多少?

    这是一个简单的循环嵌套决问题,常最规的思路是用三层循环来枚举寻找符合条件的 公鸡、母鸡、小鸡的数量,代码如下(输出结果在文章最后):
    C++;

    #include <iostream>
    using namespace std;
    int main()
    {
        int x=0,y=0,z=0;//x,y,z分别表示公鸡,母鸡和小鸡的数量 
        system("pause");
        for( x=0; x<20; x++)//公鸡的最大数量上限为20只
            for( y=0; y<33; y++)//母鸡的最大数量上限为33只
                for( z=0; z<100; z++)//小鸡的最大数量上限为100只(最多只要100只鸡)
                {
                    if( (z%3==0) && (x+y+z==100) && (5*x+3*y+z/3==100) )
                    {
                        cout<<"方案"<<i<<":"<<endl;
                        cout<<"公鸡="<<x<<"\n母鸡="<<y<<"\n小鸡="<<z<<endl;
                        i++;
                        cout<<endl;
                    }
                }
        return 0;
     } 

    接下来减少一层循环,用两层循环;

    #include <iostream>
    using namespace std;
    int main()
    {
        int x=0,y=0,z=0;//x,y,z分别表示公鸡,母鸡和小鸡的数量
        int i=1;//用于表示方案的种类 
        system("pause");
        for( x=0; x<20; x++)
            for( y=0; y<33; y++)
            {
                z = 100-x-y;//三者数量为100,小鸡(z)=100-公鸡-母鸡
                if( (z%3==0) && (x+y+z==100) && (5*x+3*y+z/3==100) )
                {
                    cout<<"方案"<<i<<":"<<endl;
                    cout<<"公鸡="<<x<<"\n母鸡="<<y<<"\n小鸡="<<z<<endl;
                    i++;
                    cout<<endl;
                }
            }
        return 0;
     } 

    最后是用一层循环,在此之前,需要列一个方程组,将其他两个变量都用剩下的那一个变量来表示,这样就能把三个变量变为一个变量,在此我们都用x(即公鸡的数量)来表示吧;
    所列方程组如下:
    5*x + 3*y + z/3 = 100;
    x + y + z = 100;
    运用一下加减消元法,可以得出y = (100 - 7 * x) / 4, z = (300 + 3 * x) / 4,这样一来的话,只有一个变量x了;我们用一层循环就可以实现了。另外,由于要满足y>=0的,所以y = (100 - 7 * x) / 4>=0可以得出x<=15;如果不限制这个条件的话,当x=16的时候y=-3,z=87也会符合条件,显然这与事实不符合(数量为负数),代码如下:

    #include <iostream>
    using namespace std;
    int main()
    {
        int x=0,y=0,z=0;//x,y,z分别表示公鸡,母鸡和小鸡的数量
        int i=1;//用于表示方案的种类 
        system("pause");
        for( x=0; x<=20; x++)
        {
            y = (100 - 7 * x) / 4;
            z = (300 + 3 * x) / 4;
            if( (z%3==0) && (x+y+z==100) && (5*x+3*y+z/3==100) )
            {
                cout<<"方案"<<i<<":"<<endl;
                cout<<"公鸡="<<x<<"\n母鸡="<<y<<"\n小鸡="<<z<<endl;
                i++;
                cout<<endl;
            }
        }
        return 0;
     } 

    结果如下:
    这里写图片描述

    展开全文
  • SQL语句优化哪些方法

    万次阅读 多人点赞 2018-01-16 16:58:26
    1.如何定位慢查询?mysql默认慢查询为10秒,如果... 主要就是三范式1p原子性:每列不可再分,比如姓名不可分,地址有可能会在分,山东可以分为济南或者聊城2p保证唯一性: 比如主键课外拓展:分布式系统如何解决并发生成订...
  • Matlab的for循环优化

    千次阅读 2013-05-13 17:29:56
    但是,该ppt中还列出了一些常用的可以用来代替循环的向量化命令,列举如下: find (find values that meet some criteria,寻找符合某些特定条件的矩阵中的元素) sum, prod, diff (sum 加, product 乘, ...
  • MySQL查询优化之五-嵌套循环连接算法(Nested-Loop Join Algorithms) 如需转载请标明出处:http://blog.csdn.net/itas109 QQ技术交流群:12951803 环境: MySQL版本:5.5.15 操作系统:windows 本文讨论嵌套...
  • JDK1.7-LinkedList循环链表优化

    千次阅读 多人点赞 2012-11-26 21:48:55
    所以LinkedList适合用于添加/删除操作频繁的情况。   --------------------------------Let’s go tothe code --------------------------------  在JDK 1.7之前(此处使用JDK1.6来举例),LinkedList是...
  • Oracle从较小结果集(驱动表/外部表)中读取一行,然后和较大结果集(被探查表/内部表)中的所有数据逐条进行比较(嵌套循环可以用于非等值连接),如果符合规则,就放入结果集中,然后取较小结果集的下一条数据继续进行...
  • 优化Python代码的4种方法

    千次阅读 2019-10-05 15:09:50
    因此,在本文中,我将借鉴我多年的编程经验来列出并展示四种可用于优化数据科学项目中Python代码的方法优化是什么? 首先定义什么是优化。我们将使用一个直观的示例进行此操作。 这是我们的问题: 假...
  • HLS会对循环结构作出具体的优化。 目的:目的,搞懂HLS对循环的操作。 UG902 v2016.4 P318:HLS用户指南中Loops内容 目录 1.对循环的操作 2.循环上限变动 2.1 无法确定latency与performance 2.2 产生报告方法...
  • DSP程序优化方法

    千次阅读 2018-07-25 11:28:15
    对程序进行优化前后,程序在DM6437平台上的运行效率能有明显的提升,常用的优化方法一般从三个方面展开。 1 对程序编译工具进行合理配置 单击project然后选择build options打开配置界面,如下图所示。 这些编译...
  • 论文阅读:ROAM: Recurrently Optimizing Tracking Model ...论文主体:跟踪分为两个模块: 1)可调整大小以适应形状变化的跟踪模型:跟踪模型包含两个分支...2)负责模型更新的神经优化器(offline):离线学习型神经优化
  • 【mysql优化 3】嵌套循环连接算法

    千次阅读 2017-08-02 21:10:53
    一个简单的嵌套循环连接(NLJ:nested-loop jon)算法,每一次运用一个循环从第一个表里读取行,通过每一行去嵌套循环连接第二个表。这个过程被重复了多次,因为还有剩余的待连接的表。 假设使用以下连接类型来执
  • Android性能优化常用方法

    千次阅读 2016-01-23 14:28:43
    本篇博客主要介绍关于性能优化的一些方法,以及性能分析工具的使用。     一 性能优化的常用方法 主要内容包括布局优化,绘制优化,内存泄露优化,相应速度优化,ListView优化,Bitmap优化,线程优化,以及...
  • 优化方法:牛顿迭代法和拟牛顿迭代法

    万次阅读 多人点赞 2014-04-27 09:18:18
    http://blog.csdn.net/pipisorry/article/details/24574293牛顿法和拟牛顿法(Newton's method & Quasi-Newton Methods)牛顿法(Newton's method) ...它是一种在实数域和复数域上近似求解方程的方法方法使用函数
  • 在上一篇文章MySQL查询语句执行过程及性能优化-基本概念和EXPLAIN语句简介中介绍了EXPLAIN语句,并举了一个慢查询例子,本篇详细说明MySQL查询执行过程原理及优化方法
  • 前端性能优化方法总结

    万次阅读 多人点赞 2017-03-20 10:25:37
    前端性能优化(一) 前端是庞大的,包括 HTML、 CSS、 Javascript、Image 、Flash等等各种各样的资源。前端优化是复杂的,针对方方面面的资源都有不同的方式。那么,前端优化的目的是什么 ?  1. 从用户角度...
  • C语言程序优化方法

    千次阅读 2013-12-07 22:58:26
    作为一个忠实的C语言程序员,经常要因为各种需要优化程序,比如:内存限制、CPU限制、网络限制、磁盘空间限制等。最近在优化公司的程序,顺便将一些优化心得总结出来和大家分享。
  • 本文介绍了基于C66x架构的常用优化技巧,首先介绍C66x相对于C64x+定点DSP的浮点和定点处理能力的增强,以及C66x新引入的128-bit的数据类型。接下来说明c66x特有的特性和相关的优化技术,重点在其浮点增强以及对复数...
  • OpenCV常见的优化方法和技巧总结

    万次阅读 多人点赞 2018-02-24 15:53:36
    OpenCV常见的优化方法和技巧总结 【尊重原创,转载请注明出处】http://blog.csdn.net/guyuealian/article/details/78540206 目录 OpenCV常见的优化方法和技巧总结 一、OpenCV常见的优化方法总结 1.1 cv::...
  • 用于实时视频和图像去雾的优化对比度增强算法

    千次阅读 多人点赞 2020-03-05 20:38:39
    该算法由一个韩国人提出,论文原文pdf版地址:https://download.csdn.net/download/HIVAN1/12188573,该论文中提出的优化对比度增强算法即可用于图像去雾,也可用于视频去雾,本文主要讲解图像去雾核心思想和方法,...
  • 史上最强Tomcat8性能优化

    万次阅读 多人点赞 2019-10-25 15:33:32
    文章目录授人以鱼不如授人以渔目的服务器资源Tomcat配置优化Linux环境安装运行Tomcat8AJP连接执行器(线程池)3种运行模式部署测试用的web项目查看服务器信息部署web应用使用Apache JMeter进行性能测试下载安装修改...
  • PBT(Population based training)是DeepMind在论文《Population Based Training of Neural Networks》中提出的一种异步的自动超参数调节优化方法。以往的自动调节超参方法可分为两类:parallel search和sequen...
  • 写在前面写这篇博客的灵感来自于自己在项目上用到的循环队列,顺便讲讲libevent中evbuffer和muduo(木铎)中buffer。循环队列循环队列是很常见的数据结构,在大学计算机课程上也会遇到,被应用到很多场景,比如管道...
  • CPU CACHE优化 性能优化方法和技巧

    千次阅读 2014-08-22 15:42:40
    性 能优化方法和技巧可以指导性能设计,但两者的方法和技巧不能等同。两者关注的对象不同。性能设计是从正向考虑问题:如何设计出高效,高性能的系统;而性 能优化是从反向考虑问题:在出现性能问题时,如何定位和...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 263,544
精华内容 105,417
关键字:

哪些方法可以用于循环优化