[HK][Furor] Benchmark: Pí közelítő értékének kiszámítása

Hi, elég világossá vált a korábbi blogbejegyzéseimre kapott hozzászólásokból, hogy sokan nagyon türelmetlenek, szeretnének még sokkal több példát látni a programnyelvemből... Végülis ezt az igényt felfoghatom dicséretnek is! Úgy döntöttem hát, legyen meg az Ő akaratuk... Thy will be done!

Azaz, bár még előbb egy csomó minden mást óhajtottam volna lefejleszteni, bizonyos dolgokat előrevettem az ütemtervben, így most módomban áll bemutatni nektek egy közismert feladatot: a Pí értékének kiszámítását egy 3 milliószor lefutó iteráció által.

Előbb bemutatom, e feladatot hogyan oldjuk meg C nyelven és Python nyelven. Íme először a C program:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int main(void) {
double p; // összegváltozó
double n; // nevező
double s; // számláló
register unsigned long long i;
clock_t CLOCK1;
clock_t CLOCK2;

p=0;
n=1;s=1;
CLOCK1=clock();
for(i=0;i<3000000; i++) {
p+=s/n;
n+=2;
s=(-1*s);
}
CLOCK2=clock();
p=p*4;
printf("idő: %g\n",(double)CLOCK2 - (double)CLOCK1);
printf("Pí közelítés: %g\n",p);

return 0;
}

Íme a Python verzió (undorodom ránézni is de ez az én egyéni szocproblémám):

import time
t0= time.time() * 1000000
result = 0.0
sign = 1.0
for n in range(3000000):
    result += sign/(2.0*n+1.0)
    sign = -sign
print (time.time()*1000000 - t0), 'millsec'
print 'Result: ', 4.0 * result

Végül a Furor nyelvű program:

tick sto clock1

#d
zero#d p one#d n one#d s
3000000 {|
@s @n / @p + sto p
@n 2. + sto n
@s -1. * sto s
|}
@p 4. * sto p
tick @clock1 #g -
."idő = " print ." tick\n"
."Pí közelítés = " @p #d printnl
end
{ „p” /* összegváltozó */ }
{ „n” /* nevező */ }
{ „s” /* számláló */ }
{ „clock1” }

A Furor futási eredménye:

idő = 205049 tick
Pí közelítés = +3.14159232025637

Na most a C programot így fordítottam:

gcc -O2 pi.c -o pic

Az így lefordított C program időeredménye 14541 tick.

A pythont így futtattam:

python pi.py

és időeredménye 1081937 lett.

Ez azt jelenti, hogy a Furor 14.1-szer lassabb mint a natív C kód, a python ellenben több mint 74-szer lassabb annál a C kódnál...

Viszont az én Furor programomnál a Python 5.276-szor lassabb ugyebár...

Mindez arra utal, hogy a nyelvem ESZMÉLETLENÜL GYORS!

Legalábbis ebben a feladatban...

Megjegyezném halkan, hogy előző programnyelvírási tapasztalataim alapján teljes bizonyossággal állíthatom, a fenti Furor példa egy összecsapott SZAR, egy gány, fos trágyahalom, tisztességes Furor programozó ilyet ki nem ad a kezéből inkább szeppukut követ el mert nem tudna ilyen szégyennel együtt élni... Azaz lesz ez még sokkal gyorsabb is! Ebből teljes mértékben hiányzik minden optimalizáció, gyorsítási lehetőség, stb. De muszáj voiltam így megírni, mert az összes ilyesmi amit elképzeltem és megálmodtam, még nincs belefejlesztve a nyelvbe. Szóval egy kis türelmeteket kérem, lesz ez még sokkal jobb is... (gyorsabb, szebb, misztikusabb, „geek”-ebb...) Persze akármit fejlesszek is bele később, a fenti egy valid, érvényes Furor kód marad! Legfeljebb nem szép...

Amint látjátok a változónevek megadásakor, nem muszáj azokat a fájl elején deklarálni. Ja, senki ne ijedjen meg, a változónevek akárhány karakteresek is lehetnek, nem kell beérnünk egy betűvel... Kiemelném azonban, ezek a részek:

{ „n” /* nevező */ }

bár változóként vannak használva e példában, de igazából - technikai értelemben - függvények, alprogramok!

Épp csak most a törzsük üres. (Pontosabban van egy "end" utasítás bennük, amit a compiler beletesz stikában, a biztonság kedvéért...). Üres a törzsük, mert most nem akarjuk őket alprogramként (is) használni. De megtehetnénk, ha akarnánk. Ez az, amire egy korábbi blogbejegyzésdemben utaltam, hogy a Furorban ugyanazt jelenti az a 3 fogalom hogy névtér, függvény és változó...

Na egyelőre ennyit erről, drága gyermekeim, a mai napra rendelt szent Furorgéliumnak vége, menjetek csicsikálni s álmodjatok a Veremtárról...

Hozzászólások

Szerkesztve: 2020. 03. 25., sze - 00:39

Java remélem paliban van a c-vel:

class test {
	public static void main(String[] args) {
		
		long startTime = System.nanoTime();
		
		double p = 0;
		double n = 1;
		double s = 1;
		for (int i = 0; i < 3000000; i++) {
			p += s / n;
			n += 2;
			s = (-1 * s);
		}
		System.out.println(System.nanoTime() - startTime + " nanosec");
		System.out.println(p * 4);

	}
}

 

futtatás:

time java test

Nos, nem ennek a topiknak a témája emiatt most nem óhajtanék belemenni a részletekbe, de jól megaszondván a Zőszinteséget, a Furor se épp egy memóriatakarékos nyelv... Az biztos hogy nem az! Ez tudatos döntés volt a részemről amúgy. Nincs ingyenebéd... A Furor GYORS, a Furor könnyen bővíthető új típusokkal, új utasításokkal, jól karbantartható, de ennek ára főként épp az hogy nem memóriatakarékos... Ez amúgy abból is sejthető hogy nála a változó ugyanaz mint az alprogram. Na és egy alprogramnak bizony elég sok mindenféle belső változója van a mindenféle dolgok adminisztrálására... Ezt természetesen minden változó esetén is lefoglalja, akkor is ha totál felesleges, mert sose lehet tudni. És tényleg nem lehet. Nem mindig lenne képes kitalálni a compiler, lesz-e az az izémizé alprogramként is használva vagy csak közönséges változóként...

És ez még csak az egyik oka, miért nem memóriatakarékos a Furor, holott van más ok is, de mondom most nem ez a téma. De sebaj, a RAM olcsó... És én magam se Furorban írnék olyan dolgokat amiknek kis helyen kell elférnie.

Obsessed commandline-maniac.

Kis fejlesztések történtek a nyelvemen az eltelt rövid idő alatt is. Íme egy fejlettebb verzió (bár még ez se a legvégső ezt előre bocsátom!):

tick sto clock1

#d
zero#d p one#d n one#d s
3000000 {|
@s @n / sum p
2. sum n
neg s
|}
4. prd p
tick @clock1 #g -
."idő = " print ." tick\n"
."Pí közelítés = " @p #d printnl
end
{ „p” /* összegváltozó */ }
{ „n” /* nevező */ }
{ „s” /* számláló */ }
{ „clock1” }

Időeredménye: 150190 tick.

Eszerint már csak 10.33-szor vagyok lassabb mint a natív C kód, és a python lassabb nálam 7.2 -ször...

Obsessed commandline-maniac.

Ha benchmarkolás, nézzük, hogyan aránylanak az idők egymáshoz 300 millió iterációval:

A fordítandókat fordítsuk le:
$ gcc -O3 pi_c.c -o pi_c
$ rustc -O pi_rust.rs

Nem bízván a belső függvényekben, time parancs segítségével is ellenőriztem (real ...):

$ time ./pi_c
idő: 1578.992000 millisec
Pí közelítés: 3.14159265
real    0m1,582s

$ time ./pi_python.py        # PyPy dolgozott a lassú cPython interpreter helyett
2931.4085 millisec
Result:  3.1415926502560234
real    0m3,045s

$ time ./pi_lua.lua
1635.685    millisec
Result:     3.1415926569227
real    0m1,640s

$ time ./pi_rust
1598 millisec
Pí közelítés: 3.1415926502560234
real    0m1,602s

 

#include <stdio.h>
#include <time.h>

int main() {
    double result = 0.0; // összegváltozó
    double nevezo = 1.0; // nevező
    double sign = 1.0; // számláló

    clock_t CLOCK1 = clock();
    for(int i=0; i<300*1000*1000; i++) {
        result += sign/nevezo;
        nevezo += 2.0;
        sign = -sign;
    }
    clock_t CLOCK2 = clock();
    printf("idő: %f millisec\n", (CLOCK2 - CLOCK1)/1000.);
    printf("Pí közelítés: %.9g\n", 4.0 * result);

    return 0;
}

 

#!/usr/bin/pypy3

import time

result = 0.0
nevezo = 1.0
sign = 1.0

t0 = time.time() * 1000000
for n in range(300_000_000):
    result += sign/nevezo
    nevezo += 2.0
    sign = -sign
t1 = time.time() * 1000000

print ((t1 - t0) / 1000., 'millisec')
print ('Result: ', 4.0 * result)

 

#!/usr/bin/luajit

local result = 0.0
local nevezo = 1.0
local sign = 1.0

local t0 = os.clock() * 1000000
for n = 0, 300*1000*1000 do
    result = result + sign/nevezo
    nevezo = nevezo + 2.0
    sign = -sign
end
local t1 = os.clock() * 1000000

print ((t1 - t0)/1000., 'millisec')
print ('Result: ', 4.0 * result)

 

use std::time::Instant;

fn main() {
    let mut result = 0.0; // összegváltozó
    let mut nevezo = 1.0; // nevező
    let mut sign = 1.0; // számláló

    let t0 = Instant::now();
    for _i in 0..300_000_000 {
        result += sign / nevezo;
        nevezo += 2.;
        sign = -sign;
    }
    let elapsed_time = t0.elapsed();

    println!("{} millisec", elapsed_time.as_millis());
    println!("Pí közelítés: {}\n", 4.0 * result);
}

A PERL nyelv is említve lett. Két évtizede (sicc!) még abban írtam a diplomamunkám webes CGI részét. De azóta a fejlesztése megragadt, semmi JIT, semmi modernizálás.
Nagyon lassú az értelmezője a korszerű, JIT-es futtatóval rendelkező szkriptnyelvekhez képest.

$ time ./pi_perl.pl
69484.402000 millisec
Result: 3.14159265
real    1m9,500s

#!/usr/bin/perl
use Time::HiRes;

my $result = 0.0;
my $nevezo = 1.0;
my $sign = 1.0;

my $t0 = Time::HiRes::gettimeofday() * 1000000;
for ($n=0; $n<300*1000*1000; $n++) {
    $result += $sign/$nevezo;
    $nevezo += 2.0;
    $sign = -$sign;
}
my $t1 = Time::HiRes::gettimeofday() * 1000000;

printf ("%f millisec\n", ($t1 - $t0)/1000.);
printf ("Result: %.8f\n", 4.0 * $result);

Köszi, ez a Perl példa jól jött. Eredménye nálam 786972, ami azt jelenti ugyebár hogy a natív C kódnál 54.12-szer lassabb, és eképp a Furornál is jóval lassabb: 12.62-ször!

Véleményem szerint a nyelvemet épp ezzel, a Perl-el meg az „eredeti” Pythonnal tisztességes összehasonlítani, és nem a JIT-es machinációkat alkalmazó izémizékkel. Az enyém ugyanis teljesen egyértelműen NEM JIT-es! Nálam a forráskódból nelkészül ugyan egy bájtkód, az a bájtkód azonban nem végrehajtható közvetlenül. Egy interpreter hajtja végre. Eképp értelmetlen az a kérdés is miféle architektúrákat támogatok. Sem,milyet, vagy ha úgy tetszik mindent, amire van C compiler. Ha képes lefordítani az én compilermet/interpreteremet, lényegében tehát a programcsomagot ami a nyelvemet alkotja, akkor a nyelvem fut azon az architektúrán. Nálam nincs JIT. Nincs lefordított és közvetlenül végrehajtható kód. Nyilván meg lehetne oldani ezt is, de eszem ágában sincs ezzel kínlasztanom magamat.

Minden olyasmi tehát amikor a Furort efféle JIT-es nyelvekkel hasonlítják össze, a szememben kissé tisztességtelen. Nyilván, ha a Furor nagyon elterjedne a világban (kész csoda lenne...) akkor meg lehetne oldani a JIT-esítését, de az egy következő lépés, erre nekem nincs semmiféle humán erőforrásom (bevallom őszintén, a kellő tudásom se, bár bizonyára meg tudnám tanulni amit kell idővel. De eszem ágában sincs...)

Jelenleg tehát az efféle összehasonlítások értelmetlenek, mert olyan mintha egy autót hasonlítanának össze egy repülőgéppel. Az olyan összehasonlítánsok a relevánsak, amik nem JIT-es verziókkal kapcsolatban történnek.

Obsessed commandline-maniac.

Sorry, de nem. Mármint, most még nem. Nem teszem közzé félkész állapotban. (és azt se tudom, ha kész lesz hogyan oszthatom meg, mert a github a Microsoft tulajdona, ergo számomra elvi okokból felejtős...)

Végiggondoltam már ezt. Abban a pillanatban hogy kiadom a kezemből, még az eddigieknél is nagyobb trollkodások jönnek majd, tengernyi gúny mindenféle teljesen jelentéktelen apróság miatt, meg jön majd a fikázás hogy milyen „stílusban” formázom a C forráskódot (mintha nem lenne tökmindegy ha egyemberes a project. De ez lenne, gondolj bele volt is már erre példa itt a HUP-on...).

De legjobb esetben is az lenne hogy küldenek majd be patch-eket meg mindent, amit át kéne néznem, döntenem felőlük mi megy bele és mi nem, amit kihagyok annak szerzője megsértődik mert mi az hogy nekem nem kell az amit ő segítőkészen csinált, és lehord majd engem nagyképűnek meg minden... nem maradna egy csepp időm se hogy ÉN MAGAM programozzak...

Szóval most még nem. Igazából kezdem úgy érezni ennyit is kár volt írnom a nyelvemről, mert máris itt a hülye vita, a szót szóramondás, az iszapbirkózás olyan teljesen agyament és a dolgokat előre nem vivő témáról, nevezhető-e programnyelvnek amit írok, mert egyesek szerint nem azt írok csak compilert (vagy interpretert), mert a nyelv szerintük valamiféle TERV csak!

Az agyam megáll komolyan!

Teljesen elvont hülye nézet a szememben. De oké, tegyük fel igaza van annak aki így véli. Nem fogadom el e nézetet de tegyük fel. NA ÉS?! Mi van akkor?! Ebben az esetben is tudja mindenki mit írok, és úgyis ezt fogom folytatni akárminek is nevezi valaki! Akkor mi a fenének ez a nagy vita róla?!

Trollkodás a javából, az, semmi egyéb! Másra se jó csak hogy elvegye az időmet. És undorító nagyon. A jó magyar szokás hogy aki nekikezd csinálni valamit azt igyekszik a drága jó magyar nép minden erővel elkedvetleníteni, visszahúzni, lehurrogni...

Szóval majd közreadom ha készen lesz. És akkor lesz készen amikor én azt mondom. Addig nem, bocs. Nem hiányzik nekem még több hülye vita mindenféle piszlicsári apróságon. Ha most tenném közzé, soha nem is lenne befejezve mert teljesen belesüppednék a sehova se vezető ocsmány viták tengerébe.

Obsessed commandline-maniac.

"(és azt se tudom, ha kész lesz hogyan oszthatom meg, mert a github a Microsoft tulajdona, ergo számomra elvi okokból felejtős...)"

Gitlab.com? Van ingyenes szolgáltatása. A szoftver részben open-source, van fizetős szolgáltatásuk és termékük is. Saját maguk hosztolják a saját kódjukat, ennek az open-source része: https://gitlab.com/gitlab-org/gitlab-foss/

BitBucket.org? Van ingyenes szolgáltatása. Ez az Atlassian szolgáltatása/terméke, van fizetős változata is.

Gitea.io? Részben nyílt forráskódú szoftver, van ingyenes szolgáltatásai is (https://gitea.com/). Magadnak is hosztolhatod. Érdekes módon, nem maguk hosztolják a saját kódjukat, hanem a GitHub, mivel nem tud annyi funkciót, mint a GitHub.

SourceForge?

Van egy csomó más szolgáltató, nem csak a GitHub, csak éppen a GitHub a legnagyobb, legismertebb és legszéleskörőbben elismert.

Köszi a tippeket. Bár bevallom, ha meg akarom osztani, lehet hogy inkább az lesz belőle hogy valahol nyitok egy honlapot, valami minimális kis tárhellyel, feldobok rá egy statikus weboldalt (netán ha többet akarok akkor egy doku-wikit), és lesz ott egy link amire kattintva le lehet tölteni a .tar.bz2 csomagot, aztán szevasz-tavasz, aki letölti kezd vele amit akar... supportot úgyse fogok nyújtani, szóval...

(természetesen a letöltött csomagban benne lesz a leírás is, minden valószínűség szerint .odt állományban).

De majd meglátom. Mindenesetre, ez nem mostanában lesz. Bevallom őszintén kissé el is ment a kedvem az egésztől, nem kis részben miattad, az értelmetlen vita miatt amibe belekényszerítettél. Ilyen hülyeségen rugózni hogy mi a programnyelv! Énédesistenkém!

Arra fel voltam készülve hogy kapok rengeteg kritikát, főleg a szintaxissal kapcsolatban. Az még jogos is lett volna valahol, és többek közt épp azért is kezdtem blogolni róla, mert hátha a sok kritika közt lesz olyan is amit érdemesnek látok megfogadni, mert tudom magamról, hogy bár a nyelveim működnek de néha tényleg teljesen agyonbonyolított jelölésrendszert alkalmazok, sajnos valóban megvan bennem az erre való hajlam... Szóval itt még jogos is lehet a kritika néha.

De azon vitázni, mi a proigramnyelv maga?! Hogy az egy TERV?! Mégis, efféle vitából mi a hasznom nekem? Mit profitál belőle a nyelv maga amit írok? (Vagy szerinted nem nyelv de az interpreterem). Vagy neked magadnak mi a hasznod egy ilyen vitából?!

Az egész arra emlékeztet engem amikor prog.mat szakon azzal kezdik a nagyképű oktatók hogy elmagyarázzák a hallgatóknak, mi az a program. Ugye szerintük a program, az egy útvonal a probléma által reprezentált (specifikált?) állapottérben...

Oké, nem vagyok hülye, képes vagyok felfogni ekkora mértékű absztrakciót. De az ég szerelmére, ennek megint SEMMI GYAKORLATI HASZNA! A számomra a program egy utasítássorozat, amit a számítógép képes végrehajtani. És kész, ennyi! Bizonyos elemi utasításokból összetákolhatóak bonyolultabb utasítások, és így tovább... Szóval tőlem aztán lehet akárhány más nézőpont, és még nem is tagadom hogy azok a nézőpontok igazak lehetnek a maguk módján. GYAKORLATI értelemben azonban sehova se vezetnek. Amikor meg akarok írni egy programot, nekem nem áll a rendelkezésemre valamiféle misztikus sokdimenziós „állapottér”, hanem csak elemi utasítások, vagy nem annyira elemi utasítások amiket az épp használt programnyelv biztosít a számomra.

És mert épp egy efféle (szerintem) programnyelvet akarok írni, aminek a gyakorlatban működnie kell, eképp muszáj vagyok a gyakorlatias megközelítéssel élni. Az elvontságot pedig meghagyom a professzoroknak.

De vitázni erről, itt... Felesleges az egész, falrahányt borsó, szófosás, semmi más haszna csak hogy igyekezzék lelombozni engem, hát nagyon szépen köszönöm, mondhatom...

Nem, nem fogok rohanni a közzétételével. Minek...

Obsessed commandline-maniac.

2020-ban faszsag csak ugy kirakni egy targzt, mert a kutyat sem erdekli ha nincs giten.

nem hiszem, hoogy azert kezdtel el bloggolni mert barki velemenye erdekel, hanem azert fosod a szot rola, hogy tudj irni valamirol. plane azt nem gondolom, hogy valtoztatnal a szintaxison, hiszen LATHATOAN SEM erdekel teged az, h BARKINEK hasznalhato legyen rajtad kivul.

mint valaki aki elvegezte a progtervmatot azt kell hogy mondjam, nagyon sok haszna van, megpedig az, hogy megtanul absztraktul _es_ egzaktul gondolkozni. segit megirni X nyelven egy Y programot? valoszinuleg nem. jobb programozo lettem tole? abszolut. (ha meg nem lattad, a ciklus definiciojat ajanlom: https://www.flickr.com/photos/nagyz/4288310109/in/dateposted-public/

 

poli, nem vagy te hulye, csak siman annyira leszarod a valo vilagot hogy amit csinalsz a vegen ertelmetlen maszlag. tok jo, hogy ha valaki forditot/interpretert tervez (nekem nem derult ki meg mindig, hogy ez most melyik, de gondolom interpreter) a sajat programozasi nyelvehez, az egyetem masodik-harmadik eveben mindenki atesik esen. a problema az, hogy nem hallgatod meg a feedbacket, mert nem erdekel teged, igy pedig nulla esely van barmilyen communityt kiepiteni a jatekszered kore.

hiszen ha mar annyira szereted gyakorlatiasan nezni: a vegen a celja csak az lehet, hogy hasznaljak masok is. ugyanis ha magadnak csinalod akkor az egadta vilagon nulla ertelme van itt bloggolnod rola. es igy vissza is kanyarodtunk az elejere amit irtam: igazabol teged nem is erdekel amit itt irunk, csak belso kenyszerbol irsz.

Ez amit írtál, igaz is meg nem is.

Igaz belőle, hogy az eddig kapott kritikák túlnyomó többsége valóban nem érdekel.

Nem igaz azonban hogy semmiféle kritika nem érdekelne engem „elvből”.

Én azért kezdtem blogolni róla, mert reméltem, kapok építő jellegű kritikákat (nem szeretem ezt a szót hogy kritika, mondjuk inkább hogy tanácsokat...) de BIZONYOS kérdésekkel kapcsolatban! BIZONYOS területeket illetően!

Sajnos azonban állandóan olyan dolgokon szívóztok amikkel kapcsolatban valóban nem akarok beleszólást engedni senkinek se, ezt elismerem őszintén. Például teljes mellszélességgel letámadtatok hogy miért RPN szintazisú a nyelvem, amikor ez „nem való” szkriptnyelvhez, nem elég modern meg más akármik. És nem értitek meg, hogy NEKEM ÉPP EZ TETSZIK!

Aztán meg jön itt a hülye szófosás hogy egyesek szerint nem is programnyelvet írok. Mert a programnyelv, az ugye a főokosok szerint csak valamiféle definíció... Teszek rá. nekem egy működősképes eszköz kell és nem filozofikus fantazmagóriákon rágódni.

Hogy compilert vagy interpretert írok? Na ezt magam se tudom. Ebben például valóban segíthetnél, hogy ezt eldöntsem! nem azt hogy mit írjak, hanem hogy minek nevezzem.

A helyzet az, hogy a forrásfájlt a programom beolvasa, majd létrehoz belőle egy belső bináris kódot. Ilyen értelemben compiler. De ez a kód NEM VÉGREHAJTHATÓ a processzor által közvetlenül! Nem futtatható! Ezt a kódot bizony egy (gyors) interpreter értelmezi! Mondhatjuk úgy, ez a bájtkód egy elképzelt virtuális számítógép gépi kódja.

Szóval egyszerre compiler és interpreter. Na ezek után döntsd el, minek a leghelyesebb nevezni, mert bevallom én magam se tudom...

Obsessed commandline-maniac.

az RPN fos, mindegy, hogy te kedveled-e. ha nem akarod h mas hasznalja, kiraly, ha viszont akarod, akkor modosits rajta mert ahogy irtam: hanyigerul nez ki jelenleg egy tetszoleges mas modern nyelvhez kepest, arrol nem is beszelve, hogy 100% nincsenek benne olyan dolgok, amitol egy nyelv modern (lambda pl)

 

nagyon egyszeru: a fordito kimenete egy nativ bytekodokbol allo, adott architecturan futtathato binaris. ha nem ilyet ad ki a cuccod, akkor nem fordit :)

és azt se tudom, ha kész lesz hogyan oszthatom meg, mert a github a Microsoft tulajdona, ergo számomra elvi okokból felejtős...

Szerintem mindketten tudjuk mar a valaszt, a MEK-be lesz feltoltve a forraskod (is) PDF formaban, mint regen, amikor a konyvtarbol kolcsonoztuk ki a jatekok Basic kodjat tartalmazo konyveket.

És megint egy új verzió! Ez már úgy körülbelül a végleges változat, azt hiszem:

tick sto clock1
#d
zero#d p one#d n one#d s
3000000 {| @s+/- @n++++ / sum p |}
4. prd p
tick @clock1 #g -
."idő = " print ." tick\n"
."Pí közelítés = " @p #d printnl
end
{ „p” /* összegváltozó */ }
{ „n” /* nevező */ }
{ „s” /* számláló */ }
{ „clock1” }

A lényeg abban a sorban van ami a 3000000 számmal kezdődik. A futási idő mindössze 52354 tick, ami azt jelenti hogy mindössze 4.288-szor vagyok lassabb mint a natív C kód... Na ezt múlja felül bármi más szkriptnyelv!

A Python meg eszerint a kanyarban sincs hozzám képest, mert 17.35-ször lassabb mint a Furor...

Jó, ismétlem és elismerem, ez a bődületes sebesség annak köszönhető, hogy e program szinte másból se áll csak egy ciklusból, ami a nyelvem különös erőssége, s a ciklusvég az utasítások jelentős százalékát teszi ki hiszen a cikluson belül is alig van utasítás. Más tesztpéldákban már sokkal kevésbé lesz ilyen versenyló a nyelvem. AZOKBAN IS GYORS LESZ, igen, nem kell szégyenkeznie... de nem lesz ENNYIRE gyors!

Kis magyarázat:

@s+/-

Ez az s változó tartalmát beteszi a veremtárba, majd a változó előjelét megváltoztatja. Mármint azon a tárhelyen változtatja meg ahol a változó van, nem a veremtárba tett tartalmon...

@n++++

Ez hasonló dolgot csinál, csak épp kettővel inkrementál.

Természetesen létezik a ++ és a -- meg a ---- postfix operátor is, melyek értelme gondolom kiderül ezek után a jelölésből...

Tervezem még több más teszt bemutatását is, de pici türelmeteket kérem, mert ezzel nagyon előreszaladtam mintegy közkívánatra. Egy csomó dolog még nincs implementálva ami alapelvárás. Például a compiler semmi hibát nem jelez ha valami olyan mnemonik van a kódban amit nem tud felismerni. Simán bennehagyja. És aztán az interpreter azt az izémizét valami utasítás pointerének értelmezi, aminek segfault a következménye az Álmoskönyv szerint... Ez a működés amúgy nem hiba, nem én vagyok a hülye hogy erre nem gondoltam, csak NEM VOLT MÉG IDŐM ezt az ellenőrzést beletenni a compilerbe, ma akartam megcsinálni de volt tőletek ez az igény hogy mutassak már valami értelmes programot más programnyelvek példáival összevetve... szóval ezt előrevettem. De van egy csomó melóm még a nyelvvel látjátok ami alapvető fontosságú de nem ilyen látványos, mégis meg kell csinálni, s idő kell hozzá... Szóval higgyétek el nagyon szépen kérlek benneteket én is boldogabb lennék ha több ilyen tesztprogramot írhatnék, hiszen EZ AZ IGAZI ÉLVEZET, igen, nekem is, mert ez látványos, meg mert lehet összehasonlítgatni stb... De muszáj egy csomó mindent még megcsinálnom, mert egyelőre a mostani állapotában a nyelvem olyan mint egy féllábú ember aki fenékberúgó versenyen indul...

Amúgy nem szándékozom telezsúfolni ellenőrző részekkel. Engem igazán nem zavar ha gyakran fut majd bele segfaultba. Elvem ugyanaz mint a FORTH esetén: a programozó dolga hogy vigyázzon...

De, azért akármennyre is ez az elvem, egy minimális kis figyelem még szerintem is elvárható a compiler részéről, szóval nálam is van azért egy abszolút minimum, s ezt bele akarom tenni. De van még egy rakás más dolog ezen felül is, szóval most hogy ez a teszt megvolt, egy kis türelmet kérek, ez nem azt jelenti hogy leáll a fejlesztés, nyugi...

Obsessed commandline-maniac.

Szerkesztve: 2020. 03. 25., sze - 03:18

Ha már stack-es programozás és PI digitjei, egy gyögyszemre akadtam:

#!/bin/dc

[K 1+k 0 1 1lxlx*+v--lx/sxlf 2*sflx .5<=]s=
[K 1+k 0 1 1lxlx*+v--lx/sxlf 2*sflx 0 .5->>]s>
[ltklxlc*ld/Lxs.Las.Lbs.Lcs.Lds.Les.Lfs.Lgs.Lss.Lts. 3Q]s@
[lbls*sblcla*ldlb*+scldla*sdlcld/sglgle=@ lgsela 2+dsas. 1 1=?]s?
[0St0Ss0Sg0Sf0Se0Sd0Sc0Sb0SaSxlx 0=< Kst 1sflx .5<= lx 0 .5->>  0lx-lx*sslfsblfsc 1sd 1se 3dsas. 1 1=? Lxs.Las.Lbs.Lcs.Lds.Les.Lfs.Lgs.Lss.Lts.0 1Q]sQ

50k
4 1lQx*ps.

Nekem is. De tenyleg kiirta a pi-t 50 jegyre. Mondjuk siman el tudom kepzelni hogy a 0St0Ss0Sg0Sf0Se0Sd0Sc0Sb0SaSxlx-hoz hasonlo reszekbe vannak bekodolva a szamjegyei, igazabol semmi sem zarja ki ezt :) 

De barhogyis, ez meg mindig emeszthetobb mint a scala!

Ettol teljesen fuggetlenul postfix notation alapjaraton egy jo dolog. Peldaul viszonylag konnyu belole x87 assembly-t csinalni vagy analitikusan derivalni egyenleteket. 

Nagyon rápörögtél a scala-ra, pedig az csak egy új paradigma. Ízlések és pofonok, hogy kinek melyik tetszik, de szerintem csak azért érzed (érezzük) könnyebbnek, mert jobban hasonlít ahhoz, amit megszoktunk (gondolom, te is valamilyen imperatív programozási nyelven (Basic, C, Fortran) nőttél fel, innen ezt is könnyebb megszokni (a stack is csak egy tömb és egy index, meg egy konvenció, hogy csak a végéről használunk, az indexet állítgatva). Az, hogy ennek van-e értelme, attól függ, hogy milyen hardveren akarod futtatni, van (volt) gép, ami tudott stack-et hardverből, és nem tudott jól címezgetni, de szerintem az én gépem nem ilyen (de ezt nem is igazán kell tudnom, mert elég gyors ahhoz, hogy a megoldandó problémákat közvetlenebbül leírni képes nyelvek fordítói elfussanak rajta).

dcnek egy rpn szamlogep, aminek stackja van. valtozoknak, amit o registernek nevez, hasonlokeppen stackek

0st az 0 storerol a t registerbe. 0St az 0 storeol a t register stackjenek tejere. az l lemasolja az utolso erteket a registerbol.

0St  0 a t-tejere

0Ss 0 a s tetejere

0Sg 0 a g tetejere

0Sf es igy tovabb

0Se

0Sd

0Sc

0Sb

0Sa

Szoval ez a kupac csak felinicializalja a registereket.

Szerkesztve: 2020. 03. 25., sze - 10:27

Jó példa a programod arra, hogy "premature optimization is the source of all evil". Hegyezed a ciklusokat, ahelyett, hogy egy jó (gyorsan konvergáló) közelítést alkalmaznál a pi-re. A tied 1/n-esen haladó alternáló sor, kicsit fáj. Ha választanál egy jobbat, pl. a Madhawa-Leibniz-formulát (valahonnan ki kell nézned a sqrt(12.d0)-t), akkor 1000 lépésben jobb eredményt kapnál.

      program pi2
      implicit none
      integer nm, i
      parameter ( nm = 1000)
      double precision smd(nm+1), res, s
      s=1.d0
      do i = 0,nm
        smd(i+1) = s/(2.d0*i+1.d0)
        s = -s/3
      end do
      res = 0.d0
      do i = nm,1,-1
        res = res + smd(i)
      end do
      write(*,*) sqrt(12.d0)*res
      end program

az eredmény:

./pi2
   3.1415926535897931

(Épp ez a magasszintű nyelvek előnye. A technikai részleteken való szellemi maszturbáció helyett a probléma lelkére fókuszálhatsz. Ez gyorsabb lesz Pythonban, mint egy szar algoritmus fényesre polírozva assemblerben.)

Nem vagyok programozó, hanem fizikus/matematikus. De pont ezt írtam már máskor a magasabb szintű nyelvek egyik fő előnyének, hogy többen képesek arra használni a számítógépet, amire való (programozni), ha a nyelv könnyen tanulható. Ezt a kis vacakot meg tudom írni én is C, C++, Fortran, Python, Algol, BASIC, ... bármelyikében, de talán a Fortranban a legkevesebb a sallang (nagyobb programot nem ebben írnék).

Nem érted. Abban teljesen igazad van hogy létezik a pí-re hatékonyabb algoritmus is. De nem ez a lényeg, hanem hogy legyen egy feladat (tökmindegy mi), különböző nyelveken leprogramozva, UGYANAZ A FELADAT, hogy a szintaxist és a nyelvek működését úgy általában össze lehessen hasonlítani. Ez volt ugyanis korábban a kérés hozzám, többetektől is, hogy mutassak már valami ilyesmit. Mutattam. Az algoritmus itt teljesen mellékes, a lényeg csak az hogy __ugyanaz__ az algoritmus legyen bemutatva mindegyik programnyelv által, s a Furor által is.

Nyilván, a te általad bemutatott hatékonyabb algoritmust (vagy akármelyik másikat is) meg lehetne írni Furorban.

És nem „hegyezem a ciklusokat”. Feltételezem, a változók postfix operátoraira gondolsz amikor ezt írod. Nem a feladat miatt találtam ki őket. Nézz csak utána, a FORTH-ban is létezik kettővel inkrementáló utasítás... Holott még azelőtt találtam ki őket hogy akár ezt tudtam volna a FORTH-ról. Azért találtam ki ezeket, mert imádom az efféle tömör jelölésrendszert, szintaxist... Nem kizárt hogy lesznek a nyelvemben még további bpostfix operátorok is, de majd még meglátom. Akad néhány ötletem, de még agyalok rajtuk hogy érdemes-e. Sajnos ha túl „misztikus” és agyonzsúfolt a jelölésrendszer, az sokak kedvét elveszi a megtanulástól. (mondjuk így se nagy az esély rá hogy bárki megtanulja rajtam kívül, de hátha...)

Na megyek fejleszteni...

Obsessed commandline-maniac.

"UGYANAZ A FELADAT, hogy a szintaxist és a nyelvek működését úgy általában össze lehessen hasonlítani."

Még mindig: nem a nyelveket hasonlítod össze, hanem az egyes nyelvi implementációk sebességét.

Az egy dolog, hogy te kevered a nyelv meg annak a fordítója/értelmezője fogalomkört, és azt hiszed, a kettő ugyanaz, de nem. Python esetén is megnézhetnéd Jython, CPython, PyPy, IronPython implementációkkal.
A C kód esetén is összehasonlíthatnád a gcc, clang, msvc, IBM C compiler, Pelles C stb. fordítókat. Mindegyiknek más és más eredménye lesz. Mert nem a nyelveket hasonlítjuk össze, hanem a fordítóprogramokat az adott nyelvre.

De hiába magyarázzuk ezt neked, szarsz te az egészre, mert nárcisztikus vagy.

Fogd már fel hogy gyakorlatiasan állok a kérdéshez!

Számomra egy programnyelv az, amit telepíthetek a gépemre, s aztán használhatom. Ennek van ugyanis GYAKORLATI HASZNA a számomra!

Nyilván amit telepítek és használok, az a te szemedben programnyelvnek tekintett platóni idea, „szubtilis elvontság” egy konkrét gyakorlati manifesztációja (implementációja) csupán, de ha több programnyelv is van a gépemen, mindegyik számára ugyanaz a vas és architektúra az adott, sőt ugyanaz az operációs rendszer is. Eképp mégis van értelme összehasonlítani a konkrét implementációkat, ha másért nem hát azért, hogy kiderüljön, az adott körülmények közt miféle jellegű feladatokat melyikkel érdemes megoldani, ha azt akarjuk hogy a futási sebesség gyors legyen!

Ez pedig sok esetben cseppet se mellékes.

Igen, ez az egyes nyelvi implementációk sebességének öszehasonlítása, oké. Elég nagy tudatlanságról árulkodik azonban részedről ha negligálod azt a közismert tényt, hogy sok olyan nyelvi konstrukció létezhet amik nem implementálhatóak a legjobb szándékkal se azonos hatékonysággal, annak ellenére hogy lényegileg ugyanazon feladatot látnák el elméletileg, vagy ha ez megvalósítható lenne is, elfogadhatatlanul sok programozói erőfeszítést igényelnének.

De figyelj, tényleg felesleges erről vitáznunk. Arra válaszolj csak, miért zavar téged ennyire, ha én szeretek programnyelvet írni, miért akarsz erről engem lebeszélni, miért akarsz letéríteni az utamról, és mi a fészkes fittyfenéért zavar téged akár csak az is ha én tényleg programnyelvek implementációjának sebességét hasonlítom össze, mert ez engem valamiért boldoggá tesz?! (Sőt láthatóan ez a téma másokat is érdekel errefelé).

Miért bánt ez téged?! Nincs jobb dolgod mint hogy velem foglalkozz? Irigy vagy tán hogy te nem tudsz egy programnyelvet írni? Vagy tudsz de lusta vagy hozzá? Miért akarod mindenáron megmérgezni mások szórakozását a kicsinyes kötekedéseddel?

Oké, tudom, majd jön megint valamiféle troll szöveg erre... sebaj, éld ki magad, legyen egy jó napod, ha téged ez boldoggá tesz, majd csak elviselem valahogy...

Obsessed commandline-maniac.

A nyelvet sokféleképpen definiálhatod. Pl. megadhatod a szintaxist BNF-fel. De definiálhatod a nyelvet egy referencia-implementációval is. Ez volt a gyakorlat akkor is, amikor még nem volt a dolognak kidolgozott elmélete (pl. az eredeti FORTRAN esetében egyáltalán nem tervezték meg a nyelvet, a fordítóprogramot írták meg, és a nyelv az volt, amit az elfogad), de később a K&R C esetében is (úgy gondolták, hogy egy ilyen kicsi, egyszerű nyelv esetében nem kell ágyúval lőni a verébre). Az már más kérdés, hogy ez ma már nem szokás, de a kicsi, egyszerűen interpretálható, RPN-t használó nyelvek sem.

A szintakszis önmagában nem elég, kell a szemantika is. A referencia-implementációs definícióval pedig sok baj van (épp erre jöttünk rá a történelem folyamán, hogy ez miért rossz), ép ezért nem csináljuk ma, nem csak azért, mert nem szokás. Mint ahogy az építészetben is rájöttünk, hogy mit hogyan érdemes csinálni. Lehetne úgy is építeni, annyira kidolgozott tervekkel, mint 2000 éve csinálták, csak sok baj van vele.

100 év múlva valószínűleg mást fogunk gondolni, de a szép, mérnöki, korrekt megoldás jelenleg a BNF vagy más hasonló környzetfüggetlen-nyelvtani leírás meg mellé a szemantika definíciója. Ez utóbbira sajnos még nincs jobb megoldás, mint az emberi nyelv, ami sokszor kétértelmű.

De ma sem csinálunk végeselem-szimulációt egy kerti házikóhoz. Egy FORTH-bonyolultságú nyelvhez valszeg bőven elég egy referencia-implementáció. Főleg, hogy mint írod, a szemantika leírására úgysincs jó módszer (esetleg még elfogadható kicsi nyelvet írni, azt körülugatni emberi nyelven, majd a library-t megírni azon a nyelven magán, de az már majdnem referencia-implementáció). Ez az egész nyelv-tervezés annyira bonyi cucc, hogy sokkal jobban megéri egy bevált nyelvet (C, C++, Fortran, Python) használni, megszokni a szarságait, mint tervezni és implementálni egy sajátot, hacsak nem ez a hobbid. Meg amúgy is, az építészek is mondják, hogy az első házat az ellenségednek építsd, a másodikat a barátodnak, és csak a harmadikat magadnak.

Oké, de őszintén kétlem hogy a FORTH megalkotója azzal kezdte volna a munkát hogy egy efféle leírást készített volna. Szerintem úgy lehetett, hogy elgondolkodott rajta, miféle nyelvet szeretne, aztán nekiállt, csinálgatta, amikor rájött hogy valami nem stimmel a tervben mert azt úgy nem lehet megcsinálni vagy lehetne de nem hatékony akkor módosított a terven, majd megint folytatta a készítést, és a végén úgy találta hogy na ez már oké.

És amikor tényleg működött egy ideje és rájött hogy nagy eséllyel nem fog több dolgot változtatni benne, legalábbis semmi igazán lényegeset, akkor UTÓLAG megcsinálta a leírását...

Obsessed commandline-maniac.

Szerintem értem. Te azt mondod, hogy egy interpretert akarsz írni, ami megért egy gépközeli nyelvet, és azt gyorsan végrehajtja. Én meg azt mondom, hogy a nyelvnek az a feladata, hogy megszabadítsa a felhasználót a lehető legjobban attól, hogy a gépre kelljen gondolnia, mert akkor marad ideje a problémát megoldani.

A valóságban nem úgy hangzik a feladat, hogy hajtsd végre ezt vagy azt az algoritmust, hanem pl. hogy számold ki a pi első 10 jegyét. És akkor eldöntheted, hogy mire fordítod az idődet, arra, hogy keress egy jó formulát, végiggondold, hogy milyen sorrendben add össze a lebegőpontos számokat, vagy pedig azzal kell foglalkozni, hogy hogyan címzek, vannak-e változóim, vagy csak egy array elemeit használhatom, azt is mindig csak a végéről (stack). Valószínűnek tartom, hogy sokkal nagyobb rutinod van a programozásban, mint nekem, mégis, azáltal, hogy egy matematikai problémák megoldására szánt nyelvet választottam, nem kellett a programozáson gondolkoznom, és a végén az eredeti feladatot a programom gyorsabban és pontosabban oldotta meg, mint a tied.

A ciklus hegyezésén azt értem, hogy fontosnak tartottad, hogy az interpretered gyorsan hajtson végre ciklusokat, míg pl. a Python vagy a Matlab esetében ezt elhanyagolták, ha tömbökkel fogalmazod meg a feladatot, gyors lesz, ha ciklusozol, pocsék. És mégis, mind a kettő remekül használható ilyen feladatokra.

Te azt mondod, hogy egy interpretert akarsz írni, ami megért egy gépközeli nyelvet, és azt gyorsan végrehajtja.

Jól látod. Így van, ezt akarom. És fentebb amit egy másik huppernek válaszoltál, ott is jól látod: Számomra az „A” Furor nyelv maga (az lesz) amit az általam készített interpreter (vagy compiler, engem az se érdekel hogy nevezzük) elfogad és végrehajt! Ő maga a nyelvem „terve”, definíciója!

Ettől persze még írok hozzá majd doksit emberi nyelven is (magyarul, de tervezem angolul is megírni).

Én meg azt mondom, hogy a nyelvnek az a feladata, hogy megszabadítsa a felhasználót a lehető legjobban attól, hogy a gépre kelljen gondolnia, mert akkor marad ideje a problémát megoldani.

Ennek a felfogásnak legalább van az én szememben is jogosultsága, nem úgy mint hülye filozófiai nevezéktan-jellegű álproblémán rágódni, hogy vajon egy csak papíron, terv formájában létező izémizé a programnyelv-e, szemben a gyakorlatban használható compilerrel... Szóval oké, ezt a nézőpontodat értem, és jogosnak is tartom bizonyos esetekben. Vélelmezem, amiatt gondolod így, mert neked meg - velem ellentétben - a matematikában lehet több jártasságod. (Bár szerénytelenül megjegyzem, átlagemberhez képest kifejezetten kimagasló matematikai tudással rendelkezem! De, az igazi matematikusoktól természetesen végtelenül távol vagyok, elismerem...).

Szóval ez így ahogy írod oké, matematikusoknak meg hasonlóknak. Én bevallom neked őszintén, néhányszor megnézegettem efféle magas szintű absztrakciókkal dolgozó nyelveket „a távolból”, mint a Haskel például, de minél jobban belemélyedtem annál nagyobb szent borzadállyal hőköltem hátra... nem az én világom! Én például ÉRTEM a rekurzió lényegét, muszáj is hogy értsem, rekurzió nélkül ezt a programnyelvemet se tudnám megalkotni... (a függvények például hierarchikusan egymásba skatulyázhatók, ide például a rekurzió elengedhetetlen). Szóval értem, tényleg, de számomra kifejezetten gusztustalan mégis amikor ezek a funkcionális nyelvek mindent rekurzióval akarnak megoldani, és nem lehet bennük egy tisztességes ciklust megszervezni, mert minden ilyesmit el akarnak rejteni a programozó elől... Oké, talán lehet bennük ciklust írni, csak én még nem jutottam el addig hogy rájöjjek hogyan...

Hasonló élményem volt az SQL -lel is. Ott is az volt hogy mindent a SELECT utasításba akartak belepréselni miközben nekem az lett volna a természetes hogy megadok egy ciklust ami végigmegy az adott fájlon, tartományon, akármin... Fertelmes, na! Nem nekem való.

Talán azért gondolkodom így, mert mint bevallottam még gyerekként a Ti-58 géppel kezdtem a tanulást aminek lényegében csak assemblyje volt, később jött a C-64 aminek volt ugyan Basicje de bármi komolyabbat akartál muszáj volt azt is assemblyben megírni... Azután meg - szinte véletlenül - a C nyelv jött ami maga is eléggé alacsony szintű. Én tehát gépközeli nyelveken tanultam a „szakmát”. Ezek az első meghatározó élményeim.

És már nem is akarok mást, túl öreg vagyok máshoz. És minek is amikor nekem ez csak hobby!

Számomra körülbelül a C++ absztrakciós szintje az ami még épp elfogadható, de igazából már azt se kedvelem túlságosan. De az még oké, hellyel-közzel. Ami attól „magasabb”, attól óvakodom.

Én egy jó szkriptnyelvet akarok, ami hatékony, de ami ugyanakkor - természetesen! - illeszkedik az ÉN megszokott gondolkozási szokásaimhoz. Ezt én teljes őszinteséggel bevallom.

Obsessed commandline-maniac.

A p változód hány bites? Inkább azt oldd meg, hogy 64 bites gépen tetszőleges tizedesjegyig számolja PI-t, amíg le nem állítod köpködje az újabb tizedeseket, mindegy az idő.

Minden változó 64 biten van tárolva. Minthogy a p egy lebegőpontos double (a C fogalmai szerint) így kihasználja e teljes 64 bitet.

És persze nyilván az általad említett feladat is megoldható lenne, de most nem ez a lényeg. Én is tudom, a fent bemutatott algoritmus nem a leghatékonyabb. Nem ez azonban a lényeg tényleg, hanem hogy ugyanaz a feladat (mindegy az algoritmus hatékonysága) különböző nyelveken hogyan van leprogramozva, és hogyan van Furorban. Gyakorlatilag tehát a szintaxisok különbsége lett bemutatva itt, e topikban.

Obsessed commandline-maniac.

Na, legalább annyival máris haladtam ma, hogy a compilerem végre kijelzi, ha ismeretlen szavakra (mnemonikokra) bukkan a forráskódban... Kiírja az ismeretlen szót, meg azt is melyik nevű függvényben bukkant rá. Ez igazán a minimálisan elvárható szolgáltatás egy compilertől ugye... mindjárt jobban érzem magamat hogy ez is készen van!

Obsessed commandline-maniac.

Well, fogalmam sincs. Rég nem foglalkozom a mauval. Számos később alkotott nyelvem jobb nála, ez meg pláne jobb lesz. De magának a maunak is létrejött több verziója, az első egy-kettő még körülbelül a Python sbességét érte el ahogy emlékszem, a későbbiek már gyorsabbak lettek mint a Python, ha jól emlékszem akkor körülbelül a natív C kód idejének 25-szörösét igényelték durván, ami nem rossz.

Nem azért váltottam tehát a mauról mintha lassú lett volna, hanem számos egyéb ok miatt. Legfőképp azért, mert a végefelé a kódbázis úgy elterebélyesedett, hogy magam is kezdtem nem kiismerni magamat rajta... Nagyon nehezen volt bővíthető új funkciókkal, stb...

Obsessed commandline-maniac.

Ha már Python, akkor inkább Python3, és fel lehet használni a nyelv adottságait. Eredeti adatok egy Chromebook-on 

2923363.5 millsec
Result:  3.1415923202563736

Míg kihasználva a list comprehension-t, más alapvető változtatás nélkül (és még indentálni sem kellett!) :

import time
t0= time.time() * 1000000
result = sum(1.0/(2.0*n+1.0) for n in range(0,3000000,2)) - sum(1.0/(2.0*n+1.0) for n in range(1,3000000,2))
print(time.time()*1000000 - t0, 'millsec')
print('Result: ', 4.0 * result)

ekkor a futási idő közel az eredeti kétharmada. (Amin még pár százalékot lehet faragni, egy függvénybe tesszük az egészet és azt hívjuk meg - lokális, globális változók közti különbség.) Persze vannak további trükkök is, de most kiegészítők nélkül játszunk, ha jól értem.

2007017.25 millsec
Result:  3.1415923202541034

AL

Igaz, valóban microsec lenne a helyes. Minő szerencse, legalább a Furor programomban viszont egyszerűen azt írom: „tick”... az egyértelmű. A Python és Perl verziókban most kijavítottam. Köszi az észrevételt! Ez végre egy valóban hasznos kritika volt!

Obsessed commandline-maniac.

Még jó, hogy az általam küldött
  - C
  - Python
  - LUA
  - Rust
  - PERL
példákban alapból odafigyeltem erre. Ezért szeretem alkalmazni a time parancsot is, mert az esetleges nagyságrendi elcsúszásaimat azonnal látom.
A PERL -t kárt hogy már nem gyorsították meg, nagyon lassú a többi megoldáshoz képest.

Szerkesztve: 2020. 03. 26., cs - 09:28

Érdekességként megjegyzem, hogy
1. FORTH alapból nem támogat floating pointot, ezért ha FORTH-ban is szeretném ugyanezt az algoritmust, az integeres aritmetikával lesz.
2. Rust-ban próbaképpen integeres aritmetikára áttérve 1,75-szörös tempó Ivy bridge architektúrán.
        AArch64 architektúrán (Odroid-C2) sokkal nagyobb a különbség az integer és float között. Integer kb. x86 laptop proci tempóval szalad.
             - Integer 1250 msec, double 5160 msec

$ rustc -O pi_integer.rs   # lefordítjuk
$ time ./pi_integer
900 millisec
Pí közelítés: 3.1415927
real    0m0,905s

use std::time::Instant;

fn main() {
    let mut result: i32 = 0; // összegváltozó
    let mut nevezo = 1; // nevező
    let mut sign = 800_000_000; // számláló

    let t0 = Instant::now();
    for _i in 0..300_000_000 {
        result += sign / nevezo;
        nevezo += 2;
        sign = -sign;
    }
    let elapsed_time = t0.elapsed();

    println!("{} millisec", elapsed_time.as_millis());
    println!("Pí közelítés: {}\n", result as f64/200_000_000.);
}

Következő lépésként jöhet a múltbeli szépséggel való játék. Vajon hogyan néz ki ez az egyszerű algoritmus FORTH-ban?
A gforth program 64 bites előjeles típussal dolgozik. Lássuk:

$ time ./pi_forth.fth
3141592650181456395
real    0m10,460s

#! /usr/bin/gforth

VARIABLE RESULT
VARIABLE NEVEZO
VARIABLE SSIGN

: PICALC
    0 RESULT !
    1 NEVEZO !
    8000000000000000000 SSIGN !

    300000000 0 DO
        SSIGN @ NEVEZO @ / RESULT +!
        2 NEVEZO +!
        0 SSIGN @ - SSIGN !
    LOOP
    RESULT @ 2 / .
;

PICALC
cr
bye

De az iménti FORTH program tovább optimalizálható, ha eljáráshívások helyett az alacsony szintű stack aritmetikára erőteljesebben támaszkodunk.

$ time ./pi_forth_opt.fth
3141592650181456395
real    0m8,884s            # előbbi 10,460s helyett

#! /usr/bin/gforth

VARIABLE RESULT
VARIABLE NEVEZO

: PICALC
    0 RESULT !
    1 NEVEZO !
    8000000000000000000 \ ez nem SSIGN regiszterbe kerül, hanem a stackbe

    300000000 0 DO
        DUP
        NEVEZO @ / RESULT +!
        2 NEVEZO +!
        0 SWAP -
    LOOP
    RESULT @ 2 / .
;

PICALC
cr
bye

és hasonlóképpen a többi változót (amely engedi magát) ahogy stack-esre átírjuk, úgy lesz
   1.) átláthatatlanabb
   2.) ám gyorsabb futású
 

A Rust-hoz képest tényleg csiga, PERL-hez képest viszont fürge.
A 10-szeres szorzó hihető, ha belegondolsz hogy az optimális, regiszteres add eax ebx helyett a stack-bázisú nyelv körbe van rakva sok "felesleges" push push pop pop utasításokkal az add előtt. A dup pedig valójában pop push push, ami szintén lassú tánc. A swap szintén pop pop push push "felesleges" időrablás.

Végülis a FORTH és társai stack bázisú elv már azzal felgyorsul, ha úgy módosítod, hogy ugyanúgy kevés regisztered van, ám az aritmetikát alacsony szinten regiszterek között is végre tudod hajtatni (jelenleg csak stack-ből). Ezáltal sok push és pop utasítást tudsz megspórolni. Azaz a stack-bázisú helyett egy stack-kel támogatott, de regiszter aritmetikát is alkalmazó nyelv sebességben jobb lehet.

Nos valóban, erre jöttem rá én is a korábbi nyelvtervezési kalandjaimból: óvakodni kell a stack birizgálásától, mint ördögnek a tömjénfüsttől!

És mindegy hogy rendszerstackról van-e szó, vagy saját magunk által implementált stack használatáról. A minimálisra kell szorítani a vele való munkát. Törekszem is erre a Furorban rendesen! Mint látható a sebességen, van is e törekvésemnek elég szép eredménye...

Obsessed commandline-maniac.

Ha a Furor nyelven írt megoldásra gondolsz, a leggyorsabb programváltozattal (itt fentebb bemutattam) ez az eredmény 300 millió iterációra:

idő = 7055069 tick
Pí közelítés = +3.14159265025602
 

Azaz picit több mint 7 másodperc.

Megmondom azonban, nem igazán értem miért ragaszkodol épp a 300 millióhoz. A 3 millió amivel én szoktam csinálni, tökéletesen megfelel az összehasonlításhoz szintén. Sőt még jobb is, mert 300 milliót nyilván sokkal tovább tart akármelyik nyelven is, így nagyobb az esély rá hogy közben a gép belekezd valami másik feladatba is, és emiatt az egész mindenség lelassul és fals eredményt kapunk.

Obsessed commandline-maniac.

Azert szoktak kicsit hosszabb futast benchmarkolni, mert igy pontosabb az eredmeny. Egy program futasakor vannak olyan idovesztesegek, amit nem jo belevenni a meresbe, pl. a program betoltesenek idejet, scriptnyelvnel a parse-olast (amibol a bytekod keletkezik), csak adott ido utan bekapcsolodo JIT idejet, es hosszabb futas eseten a meresi hiba is kisebb lesz. Ebbol persze van olyan hiba, ami kikuszobolheto (pl. ujrafuttatassal a cache-bol jon), vagy ahogy a sajat kododat is irtad: a pontos ido lekeresevel csak az eltelt idot szamolod, de ez nem mindig megoldhato. Ha parancssorbol a time paranccsal mered az idot, minden benne lesz, de ezeket a pontatlansagokat hosszabb futasido mellett el lehet hanyagolni.

When you tear out a man's tongue, you are not proving him a liar, you're only telling the world that you fear what he might say. -George R.R. Martin

Hát nálam a benchmarkolás mint a kódból is kitűnik, akkor kezdődik amikor a bájtkódot elkezdi végrehajtani az interpreter. Azaz, nincs benne az az idő, amíg a forráskódot tokenizálja. Elismerem hogy lehet azon vitatkozni, ez a szemléletmód mennyire jogos vagy sem. Nyilván ha a futtatandó Furor program nagyon nagy, esetleg jelentős lehet a bytekód előállításának időszükséglete. Másrészt viszont, benchmarkoláshoz szinte mindig olyan progit használnak amiben - mint itt is - egy (vagy több...) sokszor lefutó ciklus szerepel, abban van a lényeg, tokenizálni azonban csak egyszer kell a progit.

Obsessed commandline-maniac.

Szerintem a benchmarkolásnál ebből a szempontból nincs "igazságos" módszer úgysem, legfeljebb, ha csak nagyon hasonló futtatókörnyezeteket akarsz összehasonlítani (különben pl. felmerül, hogy ha compilert használsz, akkor bele kell-e mérni a fordítást is, vagy amit mondasz is, hogy bele kell-e mérni, amíg az interpreter betölt és tokenizál, stb.).

Amivel szerintem érdemes egy kicsit foglalkozni, az az, hogy minél különbözőbb feladatokkal is benchmarkolj, pl. a pi jegyei jól tesztelik a ciklusaidat és a lebegőpontos műveleteket, de nem nagyon használ memóriát; lehetne mellette még Fourier-transzformálni vagy mátrixműveleteket végezni, esetleg valami szövegfeldolgozást végezni (regexp-illesztés).

Gondolom, ez majd még a jövő zenéje, egyelőre értelmesebbnek látszik a funkciókat hozzáadni.

Hát nézd, az imént (az én időm szerint éjfél körül, azaz pont 10 órával azelőtt hogy e postot elküldtem) írtam egy újabb blogbejegyzést amiben egy meglehetősen komplex példaprogramot mutattam be, még ha nem is a benchmark ott a lényeg. Abban azért van memóriaelérés is...

Itt találod meg:

https://hup.hu/node/168540

De természetesen tervezek még sok-sok újabb tesztet (benchmarkokkal együtt) bemutatni, de kérlek légy egy picit türelmes velem mert láthatod, nem is gőzerővel de atomerővel fejlesztek, hiszen kb 1 héttel ezelőtt még jószerivel semmi se volt, akkor kezdtem... de nekem is időbe telik minden, ráadásul néha még velem is előfordul hogy dolgoznom kell a megélhetésért...

És a nyelvemből tényleg hiányoznak alapvető funkciók is még (bár már Turing-teljes...). Mindenesetre legközelebbre azt tervezem, hogy az lesz a teszt hogy prímszámok keresése (lényegében Eratoszthenész szitájával), Na és azért épp ezt választom, mert ennél az algoritmusnál a korábbi nyelveim tapasztalatai szerint a nyelvem nem különösebben gyors... Ezalatt NEM az értendő hogy6 lassú volna! Cseppet se! De nem vagyok képes jelentősen lekörözni a Pythont. Nagyjából vele egy sebességet tudok elérni, illetve tudtam eddig, a korábbi nyelveimben, ennél a módszernél... És azért mert itt a spéci ciklusaim nem igazán használhatóak. Mindenféle ocsmány trükkel persze itt is rá tudok verni a Python sebességére, de nem olyan igazán sokat. Most nagyon kíváncsi vagyok magam is, mi lesz ennek a tesztnek az eredménye. Nem tudom mikorra lesz kész, de ma délután már ennek kezdek neki az teljesen biztos.

Obsessed commandline-maniac.

"lehetne mellette még Fourier-transzformálni" ---> ebben tudok segíteni, GitHUB repómba tegnap kaptam ajándékként Haskell kódot is, így már 22 nyelven készen van az FFT.
Benchmarkolás miatt kizárólag a nyelv elemeivel megvalósítva.
OCaml nincs meg, továbbá FORTH és dc egyaránt hiányzik. Ha egyszer nagyon pihent leszek, megnézem meg lehet-e bennük is írni.

Bevallom a Fourier-transzformáláshoz egyáltalán nem értek. Nem azt mondom hogy kizárom hogy valaha írjak ilyen tesztet, de rengeteg, ennél fontosabb dolgom van még ezt megelőzően.

Például hogy csak egyet mondjak, egy rémségesen undorító és ocsmány feladat: DOKUMENTÁCIÓT ÍRNI a már elkészült nyelvi elemekről...

Utálom, na. Utálom, annak ellenére hogy író vagyok. De hiába, mert ez akkor se regény... Regényeket írni szeretek, dokumentációt írni nem. Ez nemcsak nem regény, de még csak nem is programozás. Nem olyan élvezetes... De amennyire tudom, ezzel nem vagyok egyedül, a legtöbb programozó nem igazán szeret dokumentációkat írni...

De akkor is muszáj. Nagy sóhajtással nekikezdtem...

Obsessed commandline-maniac.

FFT-nel sokat szamit a konkret algoritmus. Valoszinuleg tobbet szamit, mint az, hogy milyen nyelven irod. Ha jol emlekszem, a libfftw csinalta azt (lehet, hogy meg mindig, nagyon regen foglalkoztam vele), hogy a konkret gepen es megadott beallitasok mellett lefuttat tobb, benne implementalt algoritmust, lemeri ezek futasidejet, es utana a leggyorsabbat hasznalja.

When you tear out a man's tongue, you are not proving him a liar, you're only telling the world that you fear what he might say. -George R.R. Martin

Még tényleg egy csomó alapvető izémizé hiányzik, ezekkel a tesztelésekkel nagyon előreszaladtam. Például eddig úgy volt, hogy amikor tokenizál, és valahogy hibás a forrásfájl mert a záró kapcsos zárójelek száma nem azonos a nyitókéval, akkor halálnyugodtan dob egy segfaultot a compiler, és még csak hibaüzenetet se ír ki előtte...

Na ezt most javítottam.

De szóval ilyesmikkel is kell foglalkoznom, holott ezek cseppet se látványos eredmények. De fontosak, mégis. Lehet egy compiler akármilyen külalakkal formázott is, nem számít, lehet szűkszavú, lehet bőbeszédű, mindegy, de legalább a tokenizálás során ne segfaultoljon!

Mert amikor a furor program fut, runtime, az más, ott simán lehet hogy a furor programot írta meg rosszul a programozó. De amikor a forrásfájlt tokenizálja még csak?! Az már biztos hogy ha akkor van valami gebasz, az az én hibám...

Előre tudtam különben hogy ez a dolog nincs letesztelve benne (nem olyan magától értetődő mint amilyennek tűnik, különben...), de mondom, előreszaladtam mert kértetek teszteket... De most egy csomó effélét illik bepótolnom. És még azt is le kell dokumentálni ami eddig készen van... Hogy egy nagy költőt idézzek, akit szerénységem tilt megnevezni:

 

Jaj, ki tudja mennyi baj van,

Míg minden kód helyrepottyan!

Amíg robusztus nem lészen,

S itt áll majd munkára készen!

 

Obsessed commandline-maniac.