qwernet 发表于 2006-2-26 02:01:50

轻松一下,利用计算圆周率PI的程序测试MCU的性能

今天在网上看到了计算PI的一种快速算法和程序。我稍微作了一些修改,理论上可以放到任何的平台上编译执行。



#define NUMBERS                5000



long long base;

long long calc;

long long result;



void CalculatePI(long long *total, long number)

{

    long a, i, j, step;

    long array = number / 12 + 3;

    long long remain, q;

    long head, devide, devidedouble, loop, start;

    double ratio;

    for(i = 0; i <= array; i ++)

      total = 0;

    for (step = 0; step < 2; step ++)

    {

      devide = (!step) ? 5 : 239;

      devidedouble = devide * devide;

      remain = 1;

      for(i = 0;i <= array; i ++)

      {

            base=remain / devide;

//            remain=(remain%devide)*1000000000000LL;

/**/      remain=(remain - base * devide) * 1000000000000LL;

      }

      loop = (long)(number * log(10) / log(devide) + 1);

      ratio = log(devide) / log(10) / 12;

      start;

      for(i = 0; i <= array; i ++)

            calc = 0;

      for(j = 1;j <= loop; j++, j++)

      {

            start = (long)(j * ratio);

            remain = 0;

            if(!(j & 2))

                for(i = start; i <= array;)

                {

                  a=i;

//                  calc+=remain/j;

//                  remain=(remain%j)*1000000000000LL+base[++i];

/**/                q = remain / j;

/**/                calc += q;

/**/                remain -= q * j;

/**/                remain = remain * 1000000000000LL + base[++i];

                  while(calc >= 1000000000000LL)

                  {

                        calc -= 1000000000000LL;

                        calc[--a] ++;

                  }

                }

            else

                for(i = start; i <= array;)

                {

                  a=i;

//                  calc-=remain/j;

//                  remain=(remain%j)*1000000000000LL+base[++i];

/**/                q = remain / j;

/**/                calc -= q;

/**/                remain -= q * j;

/**/                remain = remain * 1000000000000LL + base[++i];

                  while(calc < 0)

                  {

                        calc += 1000000000000LL;

                        calc[-- a] --;

                  }

                }

            remain = 0;

            if(!step)

            {

                head = j/12 + 2;

                for (i = start;(i <= array) && (i <= head);)

                {

                  base = remain / devidedouble;

//                  remain=(remain%devidedouble)*1000000000000LL+base[++i];

/**/                remain -= base * devidedouble;

/**/                remain = remain * 1000000000000LL + base[++ i];

                }

            }

            else

                for(i = start;i <= array;)

                {

                  base=remain / devidedouble;

//                  remain=(remain%devidedouble)*1000000000000LL+base[++i];

/**/                remain -= base * devidedouble;

/**/                remain = remain * 1000000000000LL + base[++ i];

                }

      }

      if(!step)

      {

            total += calc * 16;

            for(i = array - 1;i >= 0;i --)

            {

                total += total / 1000000000000LL + calc * 16;

                total %= 1000000000000LL;

            }

      }

      else

      {

            long long tail;

            total -= calc * 4;

            for (i = array - 1;i >= 0;i --)

            {

                tail = total % 1000000000000LL;

                total += total / 1000000000000LL - ((tail < 0) ? 1 : 0) - calc * 4;

                total = tail + ((tail < 0) ? 1000000000000LL : 0);

            }

      }

    }

}



调用时采用语句:CalculatePI(result, NUMBERS),结果保存在long long型的数组result中,其中result存放的是数字3,result以后的以整数形式存放PI的小数部分,每个整数对应12位的小数。



我分别在PC上和ARM7(LPC2142)上测试了程序的运算速度,结果如下:



CPU       主频      RAM      编译器          计算5000位小数的时间

-----------------------------------------------------------------------

P4 2.4C   2.4GHz   512M DDR400   BCB 6.0               0.912s

C4 2.4D   2.4GHz   512M DDR333   BCB 6.0               1.285s

LPC2142   60MHz    16K SRAM    Keil ARM 2.50a,全优化    9.698s



由于代码太大,无法在我的M8515上测试,有兴趣的可以试试在AVR上的速度。迟些我也想试试在DSP上的速度如何。

kinsey 发表于 2006-2-26 11:49:57

这样也行呀?计算结果应该跟编译器和优化等级有关哦。

qwernet 发表于 2006-2-26 12:17:03

是啊,通过类似的测试,可以大致了解一下在不同平台上实现同样功能的性能差别,以及在同一MCU上不同编译器的差别(例如我就发现KARM 2.32(采用Keil编译器)比KARM 2.50(采用RealView编译器)慢很多而且不能得到正确结果),还可以比较同一编译器,不同MCU上运行的差别(例如比较各种ARM7)。

jfjarm 发表于 2006-2-26 13:08:28

我还有M128的板(外扩32KByte SRAM)

调用void CalculatePI(long long *total, long number) 就行了吗?

qwernet 发表于 2006-2-26 13:23:35

当然可以,程序代码大概20多K。你把



long long base;

long long calc;

long long result;



这3个全局变量定义到外部SRAM就可以了。

然后用定时器来算算运行时间。

qwernet 发表于 2006-2-26 14:12:28

刚才在VC下编译运行了一次,在C4 2.4D,512M DDR的配置下运行居然只需要0.176s,比BCB6.0的版本快了7倍多!

flyforyou85 发表于 2014-7-10 14:56:26

qwernet 发表于 2006-2-26 13:23
当然可以,程序代码大概20多K。你把



long long base;



我放在LPC1768上,编译不过,报错啊.

//--------------------------------------         if(!step)
         {
                                                        head = j/12 + 2;
                                                        for (i = start;(i <= array) && (i <= head);)
                                                        {
                                                  base = remain / devidedouble;   //################数组不能这样这样用吧
        //            remain=(remain%devidedouble)*1000000000000LL+base[++i];
//                      remain -= base * devidedouble;
//                      remain = remain * 1000000000000LL + base[++ i];

                                                       }
         }
          else
                                        {
            for(i = start;i <= array;)
            {
               base= (remain / devidedouble);
//            remain=(remain%devidedouble)*1000000000000LL+base[++i];
//            remain -= base * devidedouble;
//            remain = remain * 1000000000000LL + base[++ i];
            }
                                        }

数组

astankvai 发表于 2014-7-10 15:34:13

试一下ADI的blackfin DSP,应该也在1秒左右。

qwernet 发表于 2014-7-10 16:16:35

flyforyou85 发表于 2014-7-10 14:56
我放在LPC1768上,编译不过,报错啊.

//--------------------------------------         if(!step)


见鬼了,当年贴上来的代码,所有“[ i ]”都贴丢了。。。

qwernet 发表于 2014-7-10 16:19:14

flyforyou85 发表于 2014-7-10 14:56
我放在LPC1768上,编译不过,报错啊.

//--------------------------------------         if(!step)


我明白了,原来“【i】”在现在的论坛里变成了斜体格式代码,所以全部都丢了。。。

flyforyou85 发表于 2014-7-10 16:25:13

qwernet 发表于 2014-7-10 16:19
我明白了,原来“【i】”在现在的论坛里变成了斜体格式代码,所以全部都丢了。。。 ...

楼主,你好.我正想测试下手头的NXP CORTEX-M0+的,为了避免出错,能够将这个函数以及他的具体用法,放到记事本,传上来!?多谢!

redroof 发表于 2014-7-10 17:41:06

astankvai 发表于 2014-7-10 15:34
试一下ADI的blackfin DSP,应该也在1秒左右。

PC,BCB XE5 64位编译器,Win7 64位系统,CPU是I7-4700MQ,2.4G
最高优化,计算时间 28-29ms
切换为BCB XE5 32位编译器,最高优化,计算时间500ms
{:lol:}
BCB64位的进步真大!

redroof 发表于 2014-7-10 17:45:34

[ 本帖最后由 redroof 于 2014-7-10 17:46 编辑 ]\n\nredroof 发表于 2014-7-10 17:41
PC,BCB XE5 64位编译器,Win7 64位系统,CPU是I7-4700MQ,2.4G
最高优化,计算时间 28-29ms
切换为BCB XE ...

据说地球上最好的编译器是Intel的ICC
不知道哪位有新的64位版的ICC,可以编译这个代码来试试看
楼主的代码的正确处理方法是:
显示网页代码,然后把<i>替换成
然后再用浏览器打开,正常拷出里面的内容就行了
我试过,可以编译,计算结果也正确

zeroXone 发表于 2020-8-27 12:07:09

找圆周率的计算方法,找到这里,用VS2015 顺便测试了一下。
感觉挺有意思,虽然 没看懂,
使用的电脑 计算一次用时不超过50ms
win10 64位
CPU E3-1230 V2@3.30GHz
编辑后的code 重新传了一遍



// CalculatePI.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "math.h"

#define NUMBERS 5000

long long base;
long long calc;
long long result;

void CalculatePI(long long *total, long number)
{
        long a, i, j, step;
        long array = number / 12 + 3;
        long long remain, q;
        long head, devide, devidedouble, loop, start;
        double ratio;
        for (i = 0; i <= array; i++)
                total = 0;
        for (step = 0; step < 2; step++)
        {
                devide = (!step) ? 5 : 239;
                devidedouble = devide * devide;
                remain = 1;
                for (i = 0; i <= array; i++)
                {
                        base = remain / devide;
                        //            remain=(remain%devide)*1000000000000LL;
                        /**/ remain = (remain - base * devide) * 1000000000000LL;
                }
                loop = (long)(number * log(10) / log(devide) + 1);
                ratio = log(devide) / log(10) / 12;
                start;
                for (i = 0; i <= array; i++)
                        calc = 0;
                for (j = 1; j <= loop; j++, j++)
                {
                        start = (long)(j * ratio);
                        remain = 0;
                        if (!(j & 2))
                                for (i = start; i <= array;)
                                {
                                        a = i;
                                        //                  calc+=remain/j;
                                        //                  remain=(remain%j)*1000000000000LL+base[++i];
                                        /**/ q = remain / j;
                                        /**/ calc += q;
                                        /**/ remain -= q * j;
                                        /**/ remain = remain * 1000000000000LL + base[++i];
                                        while (calc >= 1000000000000LL)
                                        {
                                                calc -= 1000000000000LL;
                                                calc[--a]++;
                                        }
                                }
                        else
                                for (i = start; i <= array;)
                                {
                                        a = i;
                                        //                  calc-=remain/j;
                                        //                  remain=(remain%j)*1000000000000LL+base[++i];
                                        /**/ q = remain / j;
                                        /**/ calc -= q;
                                        /**/ remain -= q * j;
                                        /**/ remain = remain * 1000000000000LL + base[++i];
                                        while (calc < 0)
                                        {
                                                calc += 1000000000000LL;
                                                calc[--a]--;
                                        }
                                }
                        remain = 0;
                        if (!step)
                        {
                                head = j / 12 + 2;
                                for (i = start; (i <= array) && (i <= head);)
                                {
                                        base = remain / devidedouble;
                                        //                  remain=(remain%devidedouble)*1000000000000LL+base[++i];
                                        /**/ remain -= base * devidedouble;
                                        /**/ remain = remain * 1000000000000LL + base[++i];
                                }
                        }
                        else
                                for (i = start; i <= array;)
                                {
                                        base = remain / devidedouble;
                                        //                  remain=(remain%devidedouble)*1000000000000LL+base[++i];
                                        /**/ remain -= base * devidedouble;
                                        /**/ remain = remain * 1000000000000LL + base[++i];
                                }
                }
                if (!step)
                {
                        total += calc * 16;
                        for (i = array - 1; i >= 0; i--)
                        {
                                total += total / 1000000000000LL + calc * 16;
                                total %= 1000000000000LL;
                        }
                }
                else
                {
                        long long tail;
                        total -= calc * 4;
                        for (i = array - 1; i >= 0; i--)
                        {
                                tail = total % 1000000000000LL;
                                total += total / 1000000000000LL - ((tail < 0) ? 1 : 0) - calc * 4;
                                total = tail + ((tail < 0) ? 1000000000000LL : 0);
                        }
                }
        }
}
//调用时采用语句:CalculatePI(result, NUMBERS),
//结果保存在long long型的数组result中,
//其中result存放的是数字3,
//result以后的以整数形式存放PI的小数部分,
//每个整数对应12位的小数。
int main()
{
        CalculatePI(result, NUMBERS);
        return 0;
}

makesoft 发表于 2020-8-27 12:15:58

谁放在世界第一的STC上试一下{:lol:}
页: [1]
查看完整版本: 轻松一下,利用计算圆周率PI的程序测试MCU的性能