[ Tags :: pi ]

円周率10億桁を計算する #1


すずきひろのぶ氏が指摘している通り、gmp の precision のサイズの上限により、
円周率計算は6.4億桁が上限となる。
m(_ _)m 大変申し訳ございません。嘘つきました。勉強不足。
現在、gmp の precision のサイズは int (2^31-1=2,147,483,647)ではありません。従って、(2^31-1)/log210 ≑ 646,456,992 が円周率計算の上限ではありません。
nitobe@debian64:~/pi$ cat size.c
#include<stdio.h>
#include<gmp.h>

main()
{
printf("int: %d¥n", sizeof(int));
printf("long int: %d¥n", sizeof(long int));
printf("long long int: %d¥n", sizeof(long long int));
printf("mp_bitcnt_t: %d¥n", sizeof(mp_bitcnt_t));
}
nitobe@debian64:~/pi$ make size
gcc -static -O3 -m64 -mtune=amdfam10 -I/usr/local/gmp-5.0.5/include size.c -o size /usr/local/gmp-5.0.5/lib/libgmp.a
nitobe@debian64:~/pi$ ./size
int: 4
long int: 8
long long int: 8
mp_bitcnt_t: 8
nitobe@debian64:~/pi$ 
理論上の上限は、2^63-1 = 2進 9,223,372,036,854,775,807桁、(2^63-1)/log210 = 10進 2,776,511,644,261,678,565桁 ということになる。2.78E(エクサ10^18)Bit = 348P(ペタ10^15)Byteのメモリを実装したコンピュータなどそうそうあるもんじゃない。当面 gmp の上限は見られないということだ。

鋭意計算中。

12/15 23:40 追記:
pi2.c (diff)
nitobe@debian64:~/pi$ diff pi.c pi2.c
10,11c10,11
< #define LOG_TEN_TWO  3.32192809488736234789
< #define bprec(n) (int)(((n+10)*LOG_TEN_TWO)+2)
---
> #define LOG_TEN_TWO  3.3219280948873623478703194294894
> #define bprec(n) (long int)(((n+10)*LOG_TEN_TWO)+2)
16a17
>   mpz_t temp, temp2;/* add itchyny */
18c19
<   dprec = 1000000L;/* decimal precision */
---
>   dprec = 1000000000L;/* decimal precision */
21c22
<   loopmax = 21;
---
>   loopmax = 31;
22a24
>   fprintf(stderr, "%ld %d initial:", prec, loopmax); /* Add nitobe */
34,35c36,38
< 
<    mpf_set_ui (A, 1);
---
>   mpz_init (temp);/* add itchyny */
>   mpz_init (temp2);/* add itchyny */
>   mpf_set_ui (A, 1);
41a45
>   mpz_set_ui (temp2, 2);/* add itchyny */
43a48
>       fprintf(stderr, " %d:", k);
53c58,60
<       mpf_pow_ui (t2, c2, k);/* 2^k */
---
> //      mpf_pow_ui (t2, c2, k);/* 2^k */
>       mpz_pow_ui (temp, temp2, k);/* 2^k */
>       mpf_set_z (t2, temp);/* add itchyny */
59c66,67
<   mpf_pow_ui (t2, t1, 2);
---
> //  mpf_pow_ui (t2, t1, 2);
>   mpf_mul (t2, t1, t1);/* mod itchyny */
61a70
>   fprintf(stderr, " conversion:", prec, loopmax); /* Add nitobe */
64c73
<   exit(0);
---
>   return 0;/* mod nitobe */
nitobe@debian64:~/pi$ 
makefile
nitobe@debian64:~/pi$ cat makefile
CC=gcc
OPT= -static -O3 -m64 -mtune=amdfam10
GMP=gmp-5.0.5
GMP_INC=-I/usr/local/$(GMP)/include
GMP_LIB=/usr/local/$(GMP)/lib/libgmp.a
SRC= pi2.c
EXE= pi

.PHONY: clean

all: $(EXE)

pi: $(SRC)
        $(CC) $(OPT) $(GMP_INC) $(SRC) -o $(EXE) $(GMP_LIB)

size: size.c
        $(CC) $(OPT) $(GMP_INC) size.c -o size $(GMP_LIB)

clean:
rm -f pi
rm -f size
nitobe@debian64:~/pi$ 

nitobe@debian64:~/pi$ time ./pi >pi1G.txt
3321928130 31 initial: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: conversion:
real    196m38.626s
user    192m55.963s
sys     3m43.246s
nitobe@debian64:~/pi$ time ./format.sed pi1G.txt >pi1g.txt

real2m54.283s
user2m39.994s
sys0m3.148s
nitobe@debian64:~/pi$
注:実行時間は全く当てにならない。このPC上では、seti@home Link on BOINCLink 及び、World Community GridLink on BOINC がリソースの75%を占有している。

pi1g.txt
       1 3.
       2 1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
       3 8214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196

          :
          :
10000000 4219776753871319682188195635848934815504410194647387557034502943416861599324354199731814355060392734
10000001 6434543524276655356743570219396394581990548327874671398682093196353628204612755715171395115275045519
10000002 64388312
さて、この値が正しいかどうか?それが問題だ。つづく

 

— posted by nitobe at 09:35 pm   commentComment [0] 

円周率646456700桁弱を計算する #1

gmpの限界を見ておこうと思う。環境は以下の通り。
gmp-5.0.5 /gcc-4.4.5 /debian64-2.6.32-5-amd64 /VirtualBox 4.2.4 /Windows 7 /DELL XPS8300 /3.4G Intel Core i7-2600。

GNU/Linux上で円周率の計算をおこなうLink 」すずきひろのぶ氏の百万桁計算のソースを使用する。変更点は以下の通り。itchynyさんの修正も適用している。すずきひろのぶ氏が指摘している通り、gmp の precision のサイズの上限により、円周率計算は6.4億桁が上限となる。12/15追記:大嘘です円周率10億桁を計算する #1Link
nitobe@debian64:~/pi$ diff pi.c pi2.c
16a17
>   mpz_t temp, temp2;/* add itchyny */
18c19
<   dprec = 1000000L;/* decimal precision */
---
>   dprec = 800000000L;/* decimal precision */
21c22
<   loopmax = 21;
---
>   loopmax = 31;
22a24
>   fprintf(stderr, "%d initial:", loopmax); /* Add nitobe */
34,35c36,38
< 
<    mpf_set_ui (A, 1);
---
>   mpz_init (temp);/* add itchyny */
>   mpz_init (temp2);/* add itchyny */
>   mpf_set_ui (A, 1);
41a45
>   mpz_set_ui (temp2, 2);/* add itchyny */
43a48
>       fprintf(stderr, " %d:", k); /* Add nitobe */
53c58,60
<       mpf_pow_ui (t2, c2, k);/* 2^k */
---
> //      mpf_pow_ui (t2, c2, k);/* 2^k */
>       mpz_pow_ui (temp, temp2, k);/* 2^k */
>       mpf_set_z (t2, temp);/* add itchyny */
59c66,67
<   mpf_pow_ui (t2, t1, 2);
---
> //  mpf_pow_ui (t2, t1, 2);
>   mpf_mul (t2, t1, t1);/* mod itchyny */
64c72
<   exit(0);
---
>   return 0;/* mod nitobe */
nitobe@debian64:~/pi$ 
dprecで求める桁数を指定している。 loopmaxは演算繰り返し回数だが、求め得る桁数と、以下の関係がある。
loopmaxcorrect digits (about)
9<500
10<800
11<1500
12<2900
13<5700
14<11300
15<22500
16<44900
17<89600
18<179000
19<357800
20<715500
21<1430800
22<2861500
23<5722800
24<11445400
25<22890600
26<45781000
27<91561900
28<183123600
29<366247100
30<732494000

makefile
nitobe@debian64:~/pi$ cat makefile
CC=gcc
CFLAG=-static -O3
GMP=gmp-5.0.5
GMP_INC=-I/usr/local/$(GMP)/include
GMP_LIB=/usr/local/$(GMP)/lib/libgmp.a

.PHONY: clean

all: pi

pi:
        $(CC) $(CFLAG) $(GMP_INC) pi2.c -o pi $(GMP_LIB)

clean:
rm pi
nitobe@debian64:~/pi$

make して実行
nitobe@debian64:~/pi$ make
gcc -static -O3 -I/usr/local/gmp-5.0.5/include pi2.c -o pi /usr/local/gmp-5.0.5/lib/libgmp.a
nitobe@debian64:~/pi$ time ./pi > pi800M.txt
31 initial: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31:
real68m26.877s
user66m50.763s
sys1m36.338s
nitobe@debian64:~/pi$

単一行巨大ファイルは扱い難いので、百桁/行に整形する。
format.sed
nitobe@debian64:~/pi$ cat format.sed
#!/bin/sed -f
/^$/d
s/0.3/3.¥n/
s/[0-9]¥{100¥}/&¥n/g
s/e1/¥n/
nitobe@debian64:~/pi$ time ./format.sed pi800M.txt >pi800m.txt

real1m1.508s
user1m0.404s
sys0m1.108s
nitobe@debian64:~/pi$ ls -al
合計 1271884
drwxr-xr-x  2 nitobe nitobe      4096 2012-12-13 21:15 .
drwxr-xr-x 37 nitobe nitobe      4096 2012-12-13 19:50 ..
-rwxr-xr-x  1 nitobe nitobe        62 2012-12-04 21:16 format.sed
-rw-r--r--  1 nitobe nitobe       208 2012-12-13 19:49 makefile
-rwxr-xr-x  1 nitobe nitobe    854298 2012-12-13 19:49 pi
-rw-r--r--  1 nitobe nitobe      1851 2012-12-13 17:05 pi.c
-rwxr-xr-x  1 nitobe nitobe    854298 2012-12-13 19:40 pi2
-rw-r--r--  1 nitobe nitobe      2264 2012-12-13 19:48 pi2.c
-rw-r--r--  1 nitobe nitobe 646456999 2012-12-13 20:58 pi800M.txt
-rw-r--r--  1 nitobe nitobe 652921567 2012-12-13 21:08 pi800m.txt
nitobe@debian64:~/pi

8億桁を指定しているが、6億4千万桁しかない。フォーマット変換後、改行「¥n」が6百万個増えている。百桁/行フォーマットなのでエディタで開ける。重いけど。これは vi で見てみた。
      1 3.
      2 1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
      3 8214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196
    :
    :
6464569 9336326991629433891751838174109742989418332960270103331518724202832616454999878479262174537890538106
6464570 6455256718445892438033533034196466727204878408211469825653223223178441813002292106453186861390731397
6464571 2309985607826687727041129258325166030790611057861923604585439381176655074474471470989090334958

さて、この値が正しいかどうか?それが問題だ。つづく

 

— posted by nitobe at 05:34 pm   commentComment [0] 

円周率1億桁を計算する

The GNU Multiple Precision Arithmetic Library (gmp) Link の Fun: Compute billions of digits of Pi using GMP!Link にある、gmp-chudnovsky.cLink で、円周率1億桁を計算する。 gmp-5.0.5 /gcc-4.4.5 /debian64-2.6.32-5-amd64 /VirtualBox 4.2.4 /Windows 7 /DELL XPS8300 /3.4G Intel Core i7-2600。
$ cc -static -O2 -lm -I/usr/local/gmp-5.0.5/include -o pi gmp-chudnovsky.c /usr/local/gmp-5.0.5/lib/libgmp.a
$ time ./pi 100000000 1 > pi100M.txt

real 2m56.029s
user 2m53.739s
sys 0m1.948s
調子にのって、10億桁を指定したら、「セグメンテーション違反」。5億桁で「GNU MP: Cannot allocate memory (aize=159449104) アボートしました」。4億桁で「強制終了」。3億桁で、
real 11m58.979s
user 10m13.602s
sys 0m6.620s
ノーエラーで一応完了。

ちなみに、itchynyさんのコードLink も実行してみた。1億桁を指定してコンパイル/実行。
184.580s
227.850s

計算値の評価は後日。

 


— posted by nitobe at 11:20 pm   commentComment [2]  pingTrackBack [0]

 

円周率ベンチマークをやり直す


従来、「GNU/Linux上で円周率の計算をおこなうLink 」を、多倍長演算ライブラリ gmp-4.2.2 とともに使って円周率百万桁計算のベンチマークを行っていたが、gmp-5.0.5の性能がよさそうなので、再測定。すげ!
Central Processing Unit Hardware Operating System Compiler pi.c with gmp-4.2.2 pi.c with gmp-5.0.5 pi.c with gmp-5.1.0
3.4G Intel Core i7-2600 DELL XPS8300 debian64-2.6.32-5-amd64 /VirtualBox 4.2.4 /Windows 7 gcc-4.4.5 4.098s 2.209s 1.618s
2.5G Intel Core i5-3210M FUJITSU LIFEBOOK AH54/H debian64-2.6.32-5-amd64 /VirtualBox 4.2.4 /Windows 7 Home Premium gcc-4.4.5 2.188s 2.013s
3.4G Intel Core i7-2600 DELL XPS8300 ubuntu12 3.3.0-24-generic-pre /VirtualBox 4.2.4 /Windows 7 gcc-4.6.3 8.658s 4.715s
Intel(R) Pentium(R) 4 3.00GHz IBM ThinkCentre S50 8086-2KJ debian-6.0.6-i386 gcc-4.4.5 19.678s 10.441s
2.0G Intel(R) Core(TM) Duo CPU T2500 digital西行庵server CentOS release 5.5 (Final) gcc-4.1.2 22.728s 12.796s 12.776s
3.4G Intel Core i7-2600 DELL XPS8300 CYGWIN_NT-6.1-WOW64 /Windows 7 gcc-4.5.3 25.537s 13.621s
1.3G NVIDIA Tegra 3 quad-core Nexus 7 LinuxGaloula-ARMEL-3.1.10 on Android-4.1.2 gcc-4.4.5 43.991s 27.332s 17.718s
Intel(R) Pentium(R) M 1.4GHz IBM ThinkPad X31 TYPE 2672-CBJ debian -6.0.6-i386 /VirtualBox 4.2.4 /Windows XP SP3 gcc-4.4.5 40.619s 24.386s 23.257s
Intel(R) Pentium(R) M 1.3GHz IBM ThinkPad X31 TYPE 2672-B2J debian -6.0.6-i386 gcc-4.4.5 59.127s 33.236s
1.2 GHz ARM Marvell Kirkwood 88F6281 SheevaPlug Ubuntu9.04 gcc-4.3.3 1m13.602s 44.174s make不能
Broadcom BCM2835 (ARM1176JZFS (700MHz)) Raspberry Pi (model B) raspberrypi 3.2.27+ gcc-4.6.3 2m3.174s 1m17.624s 58.288s

gmp-4.2.2の4秒台って・・・以前仕事で管理していたサーバーの性能だ。うちのマシン、たいしたもんだ。今日もseti@home/boincで宇宙人を探している。常にCPUロードアベレージ100%x8だ。

Tegra3 1.3G (Nexus7)が、PenM1.4G (ThikpadX31) を抜いた!

 


— posted by nitobe at 10:00 pm   commentComment [1]  pingTrackBack [0]

Nexus 7 で pi を計算する C4droid_examples


20121104-175618


結局今回は使わなかった Nexus 7 のアプリ、C4droid (C/C++ compiler)Link n0n3m4 に付いている examples の中に、円周率を計算するサンプルコードがある。初期値2の p を、p*=((double)(((int)((i+2)/2))*2))/(((int)((i+1)/2))*2+1); で百万回回している。その割に、実行結果は、Pi = 3.141591 ・・・小数点以下5桁までしか正しくない。しょぼい。何だこりゃ?

探しましたがな。
John Wallis(1616/11/23-1703/10/28) の Arithmetica Infinitorum (1656)に出てくる、いわゆるウォリス積


かっちょよく書くと

無限乗積だ!こりやぁ収束遅いわ。式はとっても美しいんだけど。ちょっと見てみる?
Wallis
ここがexcel2010の底だよー。初めて見たでしょ。

Excel2010の行を使い尽くしてみた。超弩級に重たい。D列が近似値で、E列が真値との誤差。1,048,573回回しても小数点以下5桁までしか正しくないことが分かる。

何故、斯様な式を examples としたのか、全く意図がわからない。関孝和遺編「括要算法 貞」の、355/113 = 3.141592920・・・の方がよっぽどましだ。

ちなみに、おなじみ、Machinの公式。

Machin


arctan をTaylor展開する。9回回して小数点以下14桁をクリア。

いつもの「GNU/Linux上で円周率の計算をおこなうLink 」は、Gauss AGM。
初期値

に対し

を行うと円周率の近似値は

Gauss_AGM


わずか3回のループで小数点以下14桁をクリア。実はこの時点で小数点以下18桁までクリアしている。このアルゴリズム、pn が曲者で、1024ループあたりで変数がオーバーフローしてしまう。浮動小数点で計算するのはこの辺が限度ということだ。

実際の多桁円周率計算は、多倍長整数で計算しなければならない。

最近のトレンドは、Chudnovsky algorithm だそうな。



一項目、640320^(3/2) / 12 / 13591409 を電卓で計算すると、3.1415926535897342076684535915783・・・すげ!
二項目で27桁まで計算できちゃうみたい。

円周率を1億桁計算しました! — その試行錯誤の詳しい経緯と結果Link  プログラムモグモグ itchynyさん

Machin と Gauss_AGM の xlsx ファイルを下に置いとくので好きにして頂戴。Wallis は、70MByteもあって、ppblog に撥ねられちゃったので断念。残念。

「ウォリス一万尺」バージョンを置いときました。小数点以下3桁あたりをうろちょろしています。最終行を思う存分コピーしてください。パソコン固まっても知らないよ。自己責任。





 

— posted by nitobe at 05:59 pm   commentComment [0]  pingTrackBack [0]

T: Y: ALL: Online:
ThemeSwitch
  • Basic
Created in 0.0385 sec.
prev
2024.4
next
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30        
 
strawberry-linux geigercounter Ver.2
Sibasaki, Cyofu City, Tokyo, JAPAN
blogBar