Gambas-it

Programmazione => Progetti degli utenti => Topic aperto da: Top Fuel - 04 Ottobre 2016, 23:38:36

Titolo: Crivello di Eratostene
Inserito da: Top Fuel - 04 Ottobre 2016, 23:38:36
Semplice implementazione del Crivello di Eratostene per la ricerca dei numeri primi.
Se non sapete cosa è cercate su Wikipedia che non ho voglia di spiegarlo. :P
Ditemi che ne pensate. :)
Titolo: Re:Crivello di Eratostene
Inserito da: vuott - 05 Ottobre 2016, 00:25:09
...non ho voglia di spiegarlo. :P
E su, dai, un piccolo sforzo !    :-\






Titolo: Re:Crivello di Eratostene
Inserito da: Top Fuel - 05 Ottobre 2016, 00:39:07
E' tardi, ho sonno. :)
Titolo: Re:Crivello di Eratostene
Inserito da: Gianluigi - 05 Ottobre 2016, 13:57:23
Dovresti cambiare così l'ultimo passaggio altrimenti scrive anche 1:
Codice: [Seleziona]
For j = 1 To limite
  If serie[j] > 1 Then ListaNumeri.Add(Str$(serie[j])) 'scrive i numeri primi rimasti nella Listbox
Next

 :ciao:
Titolo: Re:Crivello di Eratostene
Inserito da: Top Fuel - 05 Ottobre 2016, 21:46:17
Beh, piccolezze... :)
Titolo: Re:Crivello di Eratostene
Inserito da: Gianluigi - 05 Ottobre 2016, 21:57:55
Beh, piccolezze... :)

Insomma (http://utenti.quipo.it/base5/numeri/curiosprimi.htm), poi vedi tu
 :ciao:
Titolo: Re:Crivello di Eratostene
Inserito da: vuott - 05 Ottobre 2016, 22:20:35


      (http://forum.ubuntu-it.org/images/smilies/whistle.gif)
Titolo: Re:Crivello di Eratostene
Inserito da: vuott - 07 Ottobre 2016, 16:54:30
All'interno del suo programma Top Fuel giustamente avverte che "sui numeri grossi (sopra il milione) il programma ci metterà parecchio".

Confrontiamo, dunque, per mera curiosità le prestazioni di Gambas con quelle di un codice scritto in C, trasformato in libreria dinamica .so richiamata successivamente in un programma Gambas.

Utilizzate un valore, ad esempio, di 10000000 (diecimilioni) per entrambe le prove - con il codice Gambas (quello già disponibile di Top Fuel) e con il codice C della libreria esterna .so - e verificate il tempo impiegato da ciascuno dei due programmi nel rispettivo processo dei dati.

Il programma Gambas che utilizzerà il codice C puro, sarà il seguente:
Codice: [Seleziona]
Private Extern Eratostene_C(limes As Integer) As Integer In "/tmp/crivello"


Public Sub Main()

Dim limite, i As Integer

 limite = 10000000

' Crea l'apposita libreria dinamica .so esterna:
  Creaso()
 
' Invoca la funzione esterna della libreria dinamica .so:
  i = Eratostene_C(limite)
  If i < 0 Then Error.Raise("Memoria insufficiente !")

End


Private Procedure Creaso()
 
  File.Save("/tmp/crivello.c", "#include <stdio.h>\n"
                               "#include <stdlib.h>\n" &
                               "#include <string.h>\n" &
                               "#include <math.h>\n\n" &
                               "int Eratostene_C(int limes) {\n\n" &
                               "   int lim, dim, i, j, z;\n" &
                               "   int *list;" &
                               "\n\n" &
                               "   dim = (limes / 2 + 1);\n" &
                               "   if((list = (int *)calloc(sizeof(int), dim)) == NULL)\n" &
                               "   return -1;\n\n" &
                               "   for(i=0; i<dim; i++)\n" &
                               "   list[i]=0;\n\n" &
                               "   printf(\"2 \");\n\n" &
                               "   lim = (int)sqrt(limes);\n\n" &
                               "   for(j=1,i=3; i<=lim; ++j,i+=2) {\n" &
                               "     if(!list[j]) {\n" &
                               "       for(z=j+i; z<dim; z+=i)\n" &
                               "         list[z] = -1;\n" &
                               "       printf(\"%d \", i);\n" &
                               "     }\n   }\n\n" &
                               "   for(; i<limes; i+=2, ++j)\n" &
                               "     if(!list[j])\n" &
                               "       printf(\"%d \", i);\n\n" &
                               "   return 0;\n\n}")
                         
  Shell "gcc -o /tmp/crivello.so /tmp/crivello.c -shared -fPIC -lm" Wait
 
End


   :-X
Titolo: Re:Crivello di Eratostene
Inserito da: Gianluigi - 07 Ottobre 2016, 17:14:16
Intanto tu non usi la grafica, poi occorrerebbe vedere se il codice scritto da Top Fuel è efficiente o si possa migliorare magari usando anche FAST.
 :ciao: :ciao:
Titolo: Re:Crivello di Eratostene
Inserito da: vuott - 07 Ottobre 2016, 17:31:36
Intanto tu non usi la grafica, poi occorrerebbe vedere se il codice scritto da Top Fuel è efficiente o si possa migliorare magari usando anche FAST.


Passi dal crivello al cavillo !

Ad ogni modo, in applicazione a riga di comando + Fast siamo quasi ai tempi del C.
Titolo: Re:Crivello di Eratostene
Inserito da: Gianluigi - 07 Ottobre 2016, 17:45:02

Passi dal crivello al cavillo !

 :D
Citazione
Ad ogni modo, in applicazione a riga di comando + Fast siamo quasi ai tempi del C.

Evvai! Evvieni! Gambas è una forza  :D :D

 :ciao: :ciao:
Titolo: Re:Crivello di Eratostene
Inserito da: vuott - 07 Ottobre 2016, 18:08:16
...questo però con valori bassi.
Se, invece, inserisco cinquencentomilioni il tempo impiegato dal C rispetto al codice Gambas è di quasi un terzo.

Inoltre volendo provare con seicentomilioni, con Gambas mi da errore di memoria esaurita :-X ; invece con la libreria esterna in C ho potuto gestire anche centomiliardi (http://forum.ubuntu-it.org/images/smilies/sisi.gif)   (non ho provato oltre) !
Titolo: Re:Crivello di Eratostene
Inserito da: Top Fuel - 08 Ottobre 2016, 00:27:10
Il mio programma era solo un piccolo esercizio, buono a scopo didattico volendo, dopo aver trovato per caso su Wikipedia questa cosa del crivello di Eratostene. :)
Se poi è venuta fuori una base di confronto e magari di miglioramento, ben venga la cosa.
Prova a parlarne sulla Mailing List, sentiamo che ti dicono. :)
Titolo: Re:Crivello di Eratostene
Inserito da: vuott - 08 Ottobre 2016, 00:46:44
Prova a parlarne sulla Mailing List, sentiamo che ti dicono.
Non ho messo in discussone il tuo codice, il quale appare essenziale, coinciso.
Ho solo fatto un mero test sui due linguaggi; nulla di più.
Titolo: Re:Crivello di Eratostene
Inserito da: Gianluigi - 08 Ottobre 2016, 17:27:20
Il mio programma era solo un piccolo esercizio, buono a scopo didattico volendo, dopo aver trovato per caso su Wikipedia questa cosa del crivello di Eratostene. :)
Se poi è venuta fuori una base di confronto e magari di miglioramento, ben venga la cosa.
Prova a parlarne sulla Mailing List, sentiamo che ti dicono. :)
Giusto quello che dice vuott, ma si può anche discutere e provare a vedere come mai Gambas esaurisce la memoria a 600 milioni.
Sul mio computer ad esempio il codice di Top Fuel la esaurisce a 300 sempre milioni.
Lascio volentieri indagare Top Fuel sul suo codice.  :P :P
Io mi sono spremuto per farlo diversamente (prendendo spunto da un articolo su internet) e pur avendo partorito il codice meno veloce (risultati su 100 milioni):
Codice: [Seleziona]
Vuott     22550,8399009705 msec / 22620,2738285065 msec
Top Fuel  36794,9628829956 msec / 36589,7300243378 msec
Gianluigi 41717,2560691833 msec / 41830,934047699 msec
sono arrivato a 2 miliardi (su 3 mi da out of bound e non memoria esaurita) anche se nell'attesa del risultato ho schiacciato un sonnellino  ;D
Allego Codice foto documentale
Nota: Se non erro il codice di Vuott non fa uso di vettori e questo potrebbe spiegare il fatto che è veloce il doppio.

Codice: [Seleziona]
' Gambas module file

Fast

Public Sub Main()

  Setaccio(100000000)

End
Private Sub Setaccio(n As Long)
 
  Dim v As New Boolean[n + 1]
  Dim l, j, i As Long 
  Dim StartTime As Float
  Dim DiffTime As Float
 
  StartTime = Timer
  l = Int(Sqr(n) + 1) 
  For i = 2 To l
    For j = i * i To n Step i     
      v[j] = True     
    Next
  Next
  For i = 2 To n
    If v[i] = False Then
      Print i
    Endif
  Next
  DiffTime = Timer - StartTime
  Print "Setaccio ", DiffTime * 1000; " msec"
 
End
:ciao: :ciao: :ciao:
Titolo: Re:Crivello di Eratostene
Inserito da: Top Fuel - 08 Ottobre 2016, 18:13:27
A 3 miliardi ti ha dato out of bound perchè il limite di elementi è 2^32-1.
Titolo: Re:Crivello di Eratostene
Inserito da: Gianluigi - 08 Ottobre 2016, 18:15:48
A 3 miliardi ti ha dato out of bound perchè il limite di elementi è 2^32-1.

Il limite di elementi di cosa?
Titolo: Re:Crivello di Eratostene
Inserito da: vuott - 08 Ottobre 2016, 18:59:42
Se non erro il codice di Vuott non fa uso di vettori e questo potrebbe spiegare il fatto che è veloce il doppio.

...c'è un Puntatore ad un Intero:
Codice: [Seleziona]
int *list

Non vi sono Moltiplicazioni.


Titolo: Re:Crivello di Eratostene
Inserito da: Gianluigi - 08 Ottobre 2016, 21:01:06
Nel mio codice quello che rallenta tanto è il secondo loop, la prima parte individua i numeri non primi mettendoli a True in 7/8 secondi, tutto il resto se lo posta via questo:
Codice: [Seleziona]
For i = 2 To n
    If v[i] = False Then
      Print i
    Endif
  Next
Purtroppo io non conosco il C, tu non potresti tradurre in gambese il codice scritto in C per vedere se funziona meglio  :D

 :ciao: :ciao:

PS Chissà Top Fuel cosa voleva dire...
Titolo: Re:Crivello di Eratostene
Inserito da: vuott - 09 Ottobre 2016, 00:57:58
...potresti tradurre in gambese il codice scritto in C ....

...gambese ?   ???
http://www.jokisaari.net/gambia/pics/gambia-map.gif

Ad ogni modo ecco la traduzione:
Codice: [Seleziona]
Public Sub Main()

  Dim limite, dime, lim, i, j, z As Integer
  Dim lista As Integer[]
 
    limite = 1000000
   
    dime = limite / 2 + 1
   
    lista = New Integer[dime]
   
    Print 2
   
    lim = Sqr(CFloat(limite))

    j = 1
    i = 3
     
    While i <= lim
      If lista[j] = 0 Then
        z = j + i
        While z < dime
          lista[z] = -1
          z += i
        Wend
        Print i
      Endif
      i += 2
      Inc j
    Wend

    While i < limite - 1
      If Not lista[j] Then Print i
      i += 2
      Inc j
    Wend

End
Titolo: Re:Crivello di Eratostene
Inserito da: Gianluigi - 09 Ottobre 2016, 14:00:27
...gambese ?   ???
http://www.jokisaari.net/gambia/pics/gambia-map.gif
:P :P :P

Ho notato che anche la console rallenta, infatti nel codice C si ottiene il result a seguire, pertanto se noi inseriamo dietro a Print nei codici in gambase  :P la virgola (il doppio punto e virgola è più lento) riduciamo il gap col C, questi i risultati su 100 milioni nel mio computer:
Codice: [Seleziona]
Crivello in C vuott   22371,8590736389 msec / 22567,2857761383 msec
Setaccio Vuott        24636,3999843597 msec / 24362,3239994049 msec
Setaccio Top Fuel     26364,4378185272 msec / 25966,2098884583 msec
Setaccio Gianluigi    30971,825838089  msec / 29990,3969764709 msec
Il nuovo codice su 2 miliardi mi da memoria terminata.
 :ciao: :ciao: :ciao:
Titolo: Re:Crivello di Eratostene
Inserito da: vuott - 09 Ottobre 2016, 15:02:11
Nei programmi Gambas puro hai usato Fast ?
Titolo: Re:Crivello di Eratostene
Inserito da: Gianluigi - 09 Ottobre 2016, 15:30:33
Nei programmi Gambas puro hai usato Fast ?

Si in tutti escluso il tuo con la libreria C, senza Fast il tuo codice impiega 30520,5111503601 msec invece di 24636,3999843597 msec
Titolo: Re:Crivello di Eratostene
Inserito da: Top Fuel - 09 Ottobre 2016, 19:37:48
A 3 miliardi ti ha dato out of bound perchè il limite di elementi è 2^32-1.

Il limite di elementi di cosa?

Il limite di elementi che può avere un array. Dall'errore si deduce che Gambas usa un intero di 4 byte per conteggiare il numero di elementi.
Titolo: Re:Crivello di Eratostene
Inserito da: Gianluigi - 10 Ottobre 2016, 10:42:51
A 3 miliardi ti ha dato out of bound perchè il limite di elementi è 2^32-1.

Il limite di elementi di cosa?

Il limite di elementi che può avere un array. Dall'errore si deduce che Gambas usa un intero di 4 byte per conteggiare il numero di elementi.

Si è vero, hai ragione.
Grazie  :ciao:
Titolo: Re:Crivello di Eratostene
Inserito da: vuott - 06 Gennaio 2017, 15:46:07

http://www.lescienze.it/news/2016/09/30/news/nuovo_metodo_calcolare_numeri_computer-3251946/
Titolo: Re:Crivello di Eratostene
Inserito da: Top Fuel - 06 Gennaio 2017, 16:16:07
Interessante, ma come fai in Gambas a leggere la cache della CPU? E sopratutto come fai a sapere in quale cache sono scritti i numeri? L1, L2, L3, core 0, core 1...
Titolo: Re:Crivello di Eratostene
Inserito da: vuott - 06 Gennaio 2017, 17:00:03
...come fai in Gambas a leggere la cache della CPU?
A mio modesto parere il problema non è se con Gambas sia possibile leggere la cache della CPU, ma più in generale "come", e soprattutto "con quali risorse di quale libreria" sia possibile.



eloaders aveva mostrato una libreria esterna (ce n'è comunque anche qualche altra) per ottenere semplicemente alcune informazioni generali sulla CPU:
http://www.gambas-it.org/smf/index.php?topic=5197.0
Non so se questa o altre consentano di leggere dentro la cache.