Aplicaciones para usar varios nucleos de tu ordenador programando en Gambas
En los ordenadores actuales, es frecuente que tengamos varios nucleos (cpus).
En gambas, en principio, solo usamos un nucleo para ejecutar nuestras aplicaciones ya que no existen los hilos (por ahora)....
Se me ha ocurrido usar procesos en gambas, para que simultaneamente se puedan ejecutar subprogramas y que resuelvan un problema de calculo en menos de tiempo.
Os lo explico con un sencillo ejemplo:Supongamos que tenemos que realizar esta operación: 345+234*34 -345+2*34
Si lo resolvieramos en un programa realizado en gambas, solo usariamos un microprocesador, y calcularía la expresion 345+234*34 -345+2*34 el solito, tardando "T" tiempo.
Ahora bien, si dividemos la operacion inicial en dos partes.
1: (345+234*34)
y 2: ( -345+2*34 )
, y cada una de ellas la ejecuta un nucleo de nuestro ordenador, en teoria se tardaria "T/2" tiempo (la mitad del tiempo inicial mas o menos).
Evidentemente para un calculo sencillo, como el del ejemplo, no merece la pena... Pero para cálculos de arboles (minimax, poda alphabeta) o algoritmos que sea posible trabajarlos de manera "paralela", el ahorro de tiempo puede ser considerable...
Os dejo aqui el ejemplo resuelto
Funciona de la siguiente manera:
- Hay dos programas: "principal-Multiproceso" y "subprograma-CalculoIntensivo"
- El "principal":
- Recibe los datos del usuario (operacion1 y operacion2), ademas del mensaje del boton operar.
- Cuando recibe el mensaje de operar, crea dos archivos de texto con las dos operaciones recibidas,
- Lanza dos procesos, (subprogramas-CalculoIntensivo"). Lo tengo pensado para mi ordenador que tiene 2 nucleos...
- Y se pone a la escucha de estos procesos "Read".
- Cada vez que recibe una lectura, comprueba que no es la ultima, si lo es pasa a operar con los todos los resultados recibidos (subrutina Total() )
'
Gambas class file
Public
numero As
Integer
=
0
Public
operaciones As
Integer
'lleva
el control de cpu que han devuelto operaciones...
Public
valorCPU1 As
Float
Public
valorcpu2 As
Float
Public
Sub
_new()
End
Public
Sub
Form_Open()
Dim
comando As
String
Dim
hproc As
Process
'averiguar
cuantos cpu tenemos
'determinamos
cuantas tareas podemos realizar simultaneamente
'url:
http://paraisolinux.com/como-saber-la-cantidad-de-procesadores-que-tengo-en-linux/
'
(en un comentario) comando: grep processor /proc/cpuinfo | wc -l
comando
=
"grep
processor /proc/cpuinfo | wc -l"
hproc
=
Shell
comando For
Read As
"NumeroCPU"
'copia
el ejecutable de calculointensivo al directorio del usuario
Try
Copy "CalculoIntensivo.gambas"
To
User.home
&
"/CalculoIntensivo.gambas"
Chmod
User.home
&
"/CalculoIntensivo.gambas"
To
"rwxrwxrwx"
End
Public
Sub
NumeroCPU_Read()
Dim
sLine As
String
Dim
sCad As
String[]
Dim
vx As
Float
Read
#Last, sLine, -50
sLine
=
Trim(sLine)
If
sLine Like
"[0-9]"
Then
operaciones
=
Val(sline)
CAMBIO(Val(SLINE))
Endif
End
Public
Sub
CAMBIO(N As
Integer)
Print
"Numero
de procesadores es de: ";
n
numero
=
n
ComboBox1.text
=
"MultiCpu
("
&
Str$(n)
&
")"
End
Public
Sub
ButtonOpera_Click()
'crear
tanto procesos como cpu halla
Dim
comando As
String
Dim
proceso1 As
Process
Dim
proceso2 As
Process
Dim
operatxt As
String
'si
tengo 2 procesadores, reparto las tareas en los dos...
'creo
dos operaciones a realizar....
operatxt
=
TextBox2.text
'"345+234*34"
File.Save(User.home
&
"/opera1.txt",
operatxt)
operatxt
=
TextBox1.text
'"-345+2*34"
File.Save(User.home
&
"/opera2.txt",
operatxt)
'creo
2 procesos...
comando
=
User.home
&
"/CalculoIntensivo.gambas
/home/uno/opera1.txt"
proceso1
=
Shell
comando For
Read As
"NumeroCPU1"
comando
=
User.home
&
"/CalculoIntensivo.gambas
/home/uno/opera2.txt"
proceso2
=
Shell
comando For
Read As
"NumeroCPU2"
'en
los procesos de lectura, compruebo si esta terminada y si lo esta
paso al calculo total...
End
Public
Sub
NumeroCPU1_Read()
Dim
sLine As
String
Dim
sCad As
String[]
Dim
vx As
Float
Read
#Last, sLine, -50
sLine
=
Trim(sLine)
valorCPU1
=
Val(sline)
operaciones
+=
-1
Print
"valorCPU1:";
valorcpu1
If
operaciones <=
0
Then
total()
End
Public
Sub
NumeroCPU2_Read()
Dim
sLine As
String
Dim
sCad As
String[]
Dim
vx As
Float
Read
#Last, sLine, -50
sLine
=
Trim(sLine)
valorCPU2
=
Val(sline)
operaciones
+=
-1
Print
"valorCPU2:";
valorcpu2
If
operaciones <=
0
Then
total()
End
Public
Sub
total()
Dim
totaloperacion As
Float
totaloperacion
=
valorCPU1 +
valorCPU2
Print
"Total
de las dos operaciones:";
totaloperacion
LabelResultado.text
=
Str$(totaloperacion)
End
- El Subprograma-CalculoIntensivo:
- Es un programa de linea de comando, que recibe como argumento el nombre del archivo que tiene la operacion
- Lee este archivo y realiza la operacion
- Escribe en la consola el resultado. Esto produce un evento "_Read" que el programa principal recibirá.
'
Gambas module file
Public
contenido As
String
Public
Sub
Main() As
String
Dim
nombrefichero As
String
Dim
operacion As
New
String[]
Dim
valor As
Float
contenido =
""
'uno
de los argumentos es el nombre de un archivo que contiene la
operacion a realizar...
nombrefichero =
LecturaArgumentos()
'abro
el archivo indicado
If
IsNull(nombrefichero)
=
False
Then
contenido =
File.Load(nombrefichero)
'leo
sus lineas
operacion =
Split(contenido,
"\n")
'proceso
operacion
Try
valor =
Eval(operacion[0])
' primera
linea es la que tiene la operacion
'escribo
resultado
Print
Str$(valor)
End
Public
Function
LecturaArgumentos() As
String
Dim
argumento As
String
Dim
lista As
New
String[]
Dim
contador As
Integer
'leo
los argumentos
For
Each
argumento In Application.Args
'añadimos
todos los argumentos a un array de cadenas
lista.add(argumento)
Next
If
lista.count
> 1
Then
'el
1º(0) argumento es el nombre del programa, el 2º(1) es el archivo a
analizar
Return
lista[1]
Else
Return
Null
Endif
End
Programa Principal:
enlace del programa principal
Subprograma:
enlace de descarga del subprograma