Dedicado a mis proyectos en Gambas ,un lenguaje de programación parecido al Visual Basic + Java pero ampliamente mejorado y...¡¡para gnu/linux!!.La potencia del gnu/linux sumada a la facilidad del Basic



Consultas, Desarrollo de programas y petición de presupuestos:



jueves, 1 de noviembre de 2012

MultiProceso: Usando 2 procesos para realizar calculos paralelos en Gambas...

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