tag:blogger.com,1999:blog-9024074870112957772024-03-13T20:30:49.572-07:00Tesis Ingeniería en InformáticaBlog anotador para la tesis de grado sobre sistemas de control de fluidos a lazo cerrado en real-time mediante método ARX usando programación GPU.Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comBlogger30125tag:blogger.com,1999:blog-902407487011295777.post-49141832037935503542012-04-17T09:50:00.000-07:002012-06-03T09:55:05.837-07:00Sistema de Control - Error con Suerte<h3>
Algoritmo de Control</h3>
Ya identificado el modelo se plantea un algoritmo de control generalizado (o Generalized Predictive Control - GPC) donde se plantea un funcional a minimizar y se itera desde un punto de inicio hacia una solución óptima tomando un paso del gradiente en cada iteración. Trataremos de dar una explicación más detallada en otro post.<br />
En este caso, la función a minimizar es la norma de los valores medidos de salida (los sensores colocados a cada lado del cilindro) más un costo por la utilización del actuador de plasma. El resultado esperado es minimizar la magnitud medida en los sensores, consiguiendo que los trazadores escurran por el eje central, utilizando la menor cantidad de energía posible en los actuadores.<br />
<br />
<h3>
Primera Implementación </h3>
La primer implementación del sistema requirió de las técnicas de comunicación ya descriptas entre Fortran y C++. En efecto, fue necesario detener el algoritmo de Code Saturne (Fortran) para informar y esperar un valor de actuación del algoritmo controlador (C++).<br />
Como agregado, dados los cambios y correcciones frecuentes en la minimización del funcional y la identificación ARX del modelo, parte del código se realizó en Matlab por lo que se empleó MEX para su ejecución.<br />
<br />
<h3>
Un Error en el Código con Resultados Prometedores</h3>
Aún luego de emplear varias horas en revisar los cálculos y comunicación entre procesos, no se pudo evitar que se filtrara un error de programación.<br />
En este caso el error fue tan simple como iniciar a cero la variable de acumulación para cada iteración. El efecto inmediato fue que el algoritmo no avanzara hacia una solución del funcional sino que mantuviera una relación de proporción con la magnitud de los trazadores. Por fortuna, esta relación también provee un esquema de control que, aunque rudimentario, resuelve el objetivo final. De esta forma el valor del actuador aumenta si la norma de los trazadores aumenta y disminuye si así lo hacen los trazadores.<br />
<br />
<h3>
Resultados de la Simulación</h3>
El resultado final es un actuador oscilante con frecuencia similar al experimento. A continuación se muestran los valores de actuación computados por el algoritmo de control. En este caso se plantea un control con inicio en el paso 6000 de la simulación, luego de entrar en régimen estacionario.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-IeJzC64p4Wk/T8uVKObs-2I/AAAAAAAABvs/lGh21aar4Ns/s1600/actuation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="http://3.bp.blogspot.com/-IeJzC64p4Wk/T8uVKObs-2I/AAAAAAAABvs/lGh21aar4Ns/s320/actuation.png" width="320" /></a></div>
El algoritmo fuerza una actuación discontínua al inicio pero luego retoma un función de oscilación suave y con la frecuencia del experimento.<br />
Los valores medidos en los sensores se pueden observar en el siguiente gráfico:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-KcXUQu1zt8s/T8uVcmV5LbI/AAAAAAAABv0/0b3HJV5YODs/s1600/scalar_values.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="http://3.bp.blogspot.com/-KcXUQu1zt8s/T8uVcmV5LbI/AAAAAAAABv0/0b3HJV5YODs/s320/scalar_values.png" width="320" /></a></div>
Luego de la actuación, y omitiendo el caso de discontinuidad, se puede observar una gran reducción en el valor medido, producto del soplido de plasma.<br />
<br />
El siguiente video ilustra los resultados previos:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dzVJ2xgZu7eIWwhVDm86suIaA90Y--rshmWXhg6J6r7UxG4rMJmiSozgSRiKS9wn8RfG-dSl8HLT8-X7X-__A' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<br />
<br />
<br />Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-67310721748597806772012-04-06T10:45:00.000-07:002012-06-03T10:45:56.137-07:00Comunicación C++ - MatlabOtro punto de contacto entre las plataformas fue encontrado en el algoritmo de control a realizar por lo que fue necesario investigar las librerías MEX.<br />
<br />El escenario es sencillo, se posee código C/C++ que debe comunicarse con Matlab enviando matrices y efectuando procesamiento con funciones de toolkits conocidos. Una vez concluido el procesamiento, se debe recuperar los valores de las matrices resultantes.<br />
<br />
Para ilustrar este tipo de comunicación dejamos un ejemplo simple sobre cómo se efectúa una operación básica en Matlab desde C/C++.<br />
<blockquote class="tr_bq" style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">#include <string.h><br />#include <stdio.h><br />#include "engine.h"<br />#define BUFSIZE 1024<br /><br />int main(int argc, char* argv[]) {<br /> Engine* ep;<br /> if (!(ep = engOpen("\0"))) {<br /> fprintf(stderr, "\nCan't start MATLAB engine\n");<br /> return 1;<br /> }<br /> else {<br /> char buffer[BUFSIZE+1];<br /> memset(buffer, 0, sizeof(buffer));<br /> engOutputBuffer(ep, buffer, sizeof(buffer) - 1);<br /> engEvalString(ep, "pi^2");<br /> printf("Evaluating: pi^2. \nResult: %s\n", buffer);<br /> engClose(ep);<br /> return 0;<br /> }<br />}</span></blockquote>
Existen ciertas compilaciones para compilar y ejecutar el código anterior. La manera más fácil es sin duda realizarlo por la consola de Matlab:<br />
<blockquote class="tr_bq" style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">>> mex('-v', '-f', fullfile(matlabroot,'bin','engopts.sh'),'main.cpp')</span><br />
<span style="font-size: x-small;"> -> g++-4.0 -c -I/Applications/MATLAB_R2010a.app/extern/include[...] -DMACI64 -DMX_COMPAT_32 -O2 -DNDEBUG "main.cpp"<br /> -> gcc-4.0 -O -Wl,-twolevel_namespace -undefined error -arch x86_64[...] -mmacosx-version-min=10.5 -o "main" main.o -L/Applications/MATLAB_R2010a.app/bin/maci64 -leng -lmx -lstdc++</span></blockquote>
<div style="font-family: "Courier New",Courier,monospace;">
</div>
<blockquote>
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">>> !./main</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">Evaluating: pi^2. </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">Result: >> </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">ans =</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> 9.8696</span></span></blockquote>
Para realizar la compilación por línea de comando, notar el uso de la variable <b>matlabroot</b>. En su directorio <b>bin</b> se puede encontrar el comando <b>mex</b> y la librería de configuración <b>engopts.sh</b>.<br />
<blockquote class="tr_bq" style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">$ /Applications/MATLAB_R2010a.app/bin/mex -v -f /Applications/MATLAB_R2010a.app/bin/engopts.sh main.cpp -o main</span></blockquote>
Si bien la compilación no se realiza con el comando <strong>gcc</strong> sino con <strong>mex</strong>, la ejecución sólo requiere que <strong>Matlab</strong> y <strong>csh</strong> estén instalados sin cambiar la línea de comando.<br />
<br />Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-10363479664857883592012-03-30T09:11:00.000-07:002012-06-03T09:12:24.223-07:00Comunicación Fortran - C++Para realizar una simulación realista del efecto que provoca el control sobre el modelo físico es necesario aplicar la actuación en simultaneo con la resolución del sistema. Para ello se plantea un esquema de comunicación entre el Code Saturne y nuestro programa en C++ donde podamos definir el valor de actuación para cada paso de la simulación.<br />
Se cuenta con varias posibilidades concretas de comunicación IPC: sockets, pipes, archivos. En este caso se opta por la comunicación mediante archivos FIFO (es decir, implementando el concepto de pipes mediante archivos virtuales) donde un programa lee del archivo mientras el otro escribe en el mismo.<br />
Para analizar la viabilidad se decide realizar un programa simple donde dos procesos se comuniquen mutuamente. En este caso contamos con un proceso que lee e imprime los valores de actuación a utilizar (hecho en Fortran 90) y otro proceso que genera y escribe los mismos (C++).<br />
<br />
<h4>
Lector (Fortran 90) - lector.f90</h4>
<pre>program readcsv
implicit none
call readAndPrint()
end program readcsv
subroutine readAndPrint()
integer status
double precision value
open(unit=99, file="act1.csv", action="read")
do
read(99, *, IOSTAT=status) value
if (status > 0) then
!Error
write (102,*) 'An error has been detected in the file'
exit
else if (status < 0) then
!EOF
exit
else
print *, 'Value:',value
end if
end do
close(99)
end subroutine
</pre>
<h4>
Escritor (C++) - escritor.cpp</h4>
<pre>#include <iostream>
#include <fstream>
#include <ctime>
int main(int argc, char* argv[]) {
std::ofstream arch("act1.csv", std::fstream::app);
for (int i = 0; i < 2; ++i) {
arch << 1.0 + i / 100.0 << std::endl;
sleep(2);
}
return 0;
} </pre>
<br />
<br />
Para ejecutar el programa es necesario abrir un archivo FIFO del sistema operativo. Esto es muy sencillo en sistemas Linux/Unix:
<br />
<pre> </pre>
<pre>mkfifo act1.csv
</pre>
<br />
La secuencia real de compilación y ejecución es la siguiente:
<br />
<pre> </pre>
<pre>$ gfortran -o lector lector.f90
$ g++ -o escritor escritor.cpp
$ mkfifo act1.csv
$ ./lector &
[1] 892 </pre>
<pre>$ ./escritor</pre>
<pre> Value: 1.0000000000000000
Value: 1.0100000000000000
[1]+ Done ./lector</pre>Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-22600222935993181032012-03-07T11:39:00.000-08:002012-05-16T11:39:42.863-07:00Reducción de Variables y agregado de Trazadores<h3>
Sensores </h3>
Luego de las primeras pruebas con el algoritmo ARX propio del laboratorio, y teniendo en cuenta los pobres resultados de <i>performance </i>y precisión para grandes cantidades de variables, se decide simplificar el problema de estudio a un conjunto reducido de sensores.<br />
Como primer aproximación se plantea la utilización de 4 únicos puntos sensores y la medición de la presión en esos puntos.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-2UMUfG7Vy-E/T7O77Tv_j8I/AAAAAAAABvU/UJtQ51oHw78/s1600/line.probes.4.sensors.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="216" src="http://4.bp.blogspot.com/-2UMUfG7Vy-E/T7O77Tv_j8I/AAAAAAAABvU/UJtQ51oHw78/s320/line.probes.4.sensors.png" width="320" /></a></div>
<br />
Los puntos se encuentran simétricos al eje X por lo que se espera una función espejada en cada par de los mismos. Los puntos colocados en la segunda línea de sensores deberían mantener cierta similitud con los de la primer línea pero con un decaimiento en la intensidad debido a la difusión más un retardo en el tiempo por la velocidad del escurrimiento.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-vUn_GKAZ78o/T7P0RC-IPhI/AAAAAAAABvg/mO1r_pkrAoA/s1600/scalar_values.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="185" src="http://2.bp.blogspot.com/-vUn_GKAZ78o/T7P0RC-IPhI/AAAAAAAABvg/mO1r_pkrAoA/s400/scalar_values.png" width="400" /></a></div>
<br />
<br />
<h3>
Trazadores</h3>
Si bien esta información se puede obtener en el simulador CodeSaturne, es necesario idear un método de procesamiento que permita calcularla de las imágenes a obtener en el experimento real. Por tal motivo se decide agregar trazadores a la simulación que serán implementados con fuentes de humo (u otras sustancias que queden en suspención sobre el fluido) al montar el experimento.<br />
A tal fin se agregan escalares a la simulación del Code Saturne como se observa a continuación:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dxFF_8NMna3S61_3CR8Rjd-A6vD5zDyuFlcI5JDvHftTtnKf6ioxBBxODJDl4ZF7pK3dgqG-MebX8kEUpPRQA' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<br />Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-24798558849594148752012-02-07T07:35:00.000-08:002012-06-03T09:55:21.631-07:00ARX - Resultados del Algoritmo con Información RealLuego de escribir el algoritmo ARX que soporte grandes vólumenes de información se decide ponerlo en práctica con los datos experimentales obtenidos de la simulación del Code Saturne.<br />
De esta forma se pretende obtener resultados más cercanos a los esperados de la experiencia real y comprobar que los algoritmos escritos hasta el momento sean efectivos y eficaces.<br />
Se practican varias pruebas con los valores de vorticidad obtenidos de la simulación obtenidos mediante una grilla definida en la zona de la estela del cilindro. Se colocan varias líneas de obtención de información y por cada línea se relevan aprox. 50 puntos en 500 pasos de tiempo a lo largo de 20 líneas.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-6_GKxgT8pNY/TzPqCa_F7xI/AAAAAAAABr4/nmjLlEt8w6c/s1600/line.probes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="254" src="http://4.bp.blogspot.com/-6_GKxgT8pNY/TzPqCa_F7xI/AAAAAAAABr4/nmjLlEt8w6c/s320/line.probes.png" width="320" /></a></div>
<br />
<br />
<br />
Los resultados obtenidos con el total de la información no fueron satisfactorios. Las simulaciones divergen y se demoran mucho tiempo.<br />
A fin de determinar un buen número de muestras a utilizar se realizan distintas comparaciones planteando configuraciones de: cantidad de líneas utilizadas, cantidad de muestras por línea, cantidad de pasos de simulación a predecir (antes de poder relevar los valores reales y poder realimentar al predictor). Los resultados fueron positivos siempre que se utilizaran menos de 200 variables de entrada. Se puede ver el porcentaje de ajuste para las distintas configuraciones en el siguiente gráfico:<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-NOsIJu5QZ78/TzPncJYt_pI/AAAAAAAABrw/gD7ghN15aNc/s1600/ArxComparisonWithNoise0.5Percent.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="291" src="http://2.bp.blogspot.com/-NOsIJu5QZ78/TzPncJYt_pI/AAAAAAAABrw/gD7ghN15aNc/s400/ArxComparisonWithNoise0.5Percent.png" width="400" /></a></div>
<br />Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-48047435004089985512012-01-24T11:00:00.000-08:002012-02-09T06:27:38.696-08:00ARX - Algoritmo propio para identificación del sistemaEl algoritmo provisto por Matlab demostró funcionar a la perfección con las series de ejemplo pero al intentar utilizarlo con volúmenes de datos más grandes los tiempos de cómputo crecen exponencialmente. Como agregado, el sistema final debe programarse en C/C++/CUDA donde la utilización del toolkit de Matlab es poco práctica.<br />
En consecuencia se decide implementar la identificación del modelo ARX. A tal fin se analizan ciertas publicaciones de Lennart Ljung (autor del toolkit de Matlab) y se consigue un algoritmo que entrega resultados similares en menor tiempo.<br />
Para comprobar la bondad del algoritmo creado se realizan comparaciones contra los modelos obtenidos con el toolkit de Matlab para las series 'Motorized Camera' y 'Missile' previamente estudiadas.<br />
Se utiliza la función <b>compare </b>del toolkit para verificar el ajuste con muy buenos resultados. Las siguientes imágenes muestran la comparación gráfica entre los resultados obtenidos por Matlab (llamado model) y por el algoritmo basado en los escritos de Ljung (llamado modelLjung):<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://4.bp.blogspot.com/-3OE3Y64wE-E/TzPW0lQwqYI/AAAAAAAABq4/1lnbJMluRew/s1600/MotorizedCamera.ARX.Detection.Comparison.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="277" src="http://4.bp.blogspot.com/-3OE3Y64wE-E/TzPW0lQwqYI/AAAAAAAABq4/1lnbJMluRew/s400/MotorizedCamera.ARX.Detection.Comparison.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Serie 'Motorized Camera'. Comparación entre algoritmos de identificación.</td></tr>
</tbody></table>
<br />
<br />
<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://4.bp.blogspot.com/-MBGgh6-aOKE/TzPWz-V4TPI/AAAAAAAABqw/q7yI1Jo9aFQ/s1600/Missile.ARX.Detection.Comparison.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="228" src="http://4.bp.blogspot.com/-MBGgh6-aOKE/TzPWz-V4TPI/AAAAAAAABqw/q7yI1Jo9aFQ/s400/Missile.ARX.Detection.Comparison.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Serie 'Missile'. Comparación entre algoritmos de identificación.</td></tr>
</tbody></table>
<br />Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-87690503236926655682012-01-16T10:32:00.000-08:002012-02-09T07:22:00.743-08:00ARX - Identificación del SistemaEl modelo físico a estudiar debe estar representado en el software de control de forma tal que sea posible predecir los futuros estados y determinar cual es la mejor actuación para poder conseguir el resultado deseado.<br />
Existen varias maneras de modelar numéricamente una experiencia física. En este caso optamos por un modelo de caja negra llamado Auto Regressive with eXogenous input (ARX). En este modelo, es necesario definir grandes matrices de coeficientes que permitan, dado un vector de estado con información de pasos previos, obtener una predicción a futuro del sistema. Como todo modelo de caja cerrada, los coeficientes necesarios son definidos 'por inspección' o con métodos de identificación en base a mediciones previas.<br />
<br />
La ecuación que define el modelo ARX más simple, una entrada y una salida (SISO), es la siguiente:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-cvaL0_OMfeI/TzPeC4DDPhI/AAAAAAAABrA/_UiHDpuQPB0/s1600/ARX_time_equation.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="20" src="http://1.bp.blogspot.com/-cvaL0_OMfeI/TzPeC4DDPhI/AAAAAAAABrA/_UiHDpuQPB0/s640/ARX_time_equation.gif" width="640" /></a></div>
<br />
donde:<br />
<blockquote class="tr_bq">
y: variable de salida del sistema<br />u: variable de entrada del sistema<br />
a y b: coeficientes asociados</blockquote>
<br />
En caso de tener un sistema con entradas y salidas múltiples (MIMO), las variables <b>u</b> e <b>y</b> se transforman en vectores (un componente de <b>u</b> por cada entrada, un componente de <b>y</b> por cada salida). Sin cambios en la ecuación, se la puede extender a la forma matricial para representar ese esquema.<br />
Por último, los coeficientes <b>a</b> y <b>b</b> se pueden agrupar utilizando una notación reducida:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-yZSryqE9kwQ/TzPjugYh4KI/AAAAAAAABrQ/GsWuOuYKXIY/s1600/ARX_Z_ecuation.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-yZSryqE9kwQ/TzPjugYh4KI/AAAAAAAABrQ/GsWuOuYKXIY/s1600/ARX_Z_ecuation.gif" /></a></div>
<br />
Donde se definen las matrices de polinomios A y B según:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-eXkErMsKZ5s/TzPj48dJEZI/AAAAAAAABrY/ONhsW_OkcFU/s1600/ARX_A_definition.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-eXkErMsKZ5s/TzPj48dJEZI/AAAAAAAABrY/ONhsW_OkcFU/s1600/ARX_A_definition.gif" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-P4Jd1cqS5IA/TzPj6Fwvc6I/AAAAAAAABrg/eu9GVYUIspo/s1600/ARX_B_definition.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-P4Jd1cqS5IA/TzPj6Fwvc6I/AAAAAAAABrg/eu9GVYUIspo/s1600/ARX_B_definition.gif" /></a></div>
<br />
Siendo Z el operador de corrimiento:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-l8YXLSNgPkc/TzPkBEHd6CI/AAAAAAAABro/7l9TVEqmP9s/s1600/Z_backward_shift_operator.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-l8YXLSNgPkc/TzPkBEHd6CI/AAAAAAAABro/7l9TVEqmP9s/s1600/Z_backward_shift_operator.gif" /></a></div>
<br />
<br />
<br />
<br />
<br />
En todos los casos se debe entender la existencia de un término de error en cualquiera de los lados de la igualdad que corrige las incertezas que provoca el modelo a caja cerrada. Con esto en mente, se puede entender el modelo con el siguiente esquema:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-7LWgYkGHZ1s/TzPeXDg7tyI/AAAAAAAABrI/lDseiOS0AuE/s1600/ARX_block_diagram.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="56" src="http://3.bp.blogspot.com/-7LWgYkGHZ1s/TzPeXDg7tyI/AAAAAAAABrI/lDseiOS0AuE/s200/ARX_block_diagram.gif" width="200" /></a></div>
<br />
<br />Matlab posee un toolkit de identificación de sistemas que entrega el modelo ARX computado a partir de una serie de muestras. Para probar el toolkit utilizamos series predefinidas en Matlab llamadas 'Motorized Camera' y 'Missile' que incluyen datos reales de varios sensores.<br />
Se puede obtener más información sobre el algoritmo y las funciones utilizadas desde <a href="http://www.mathworks.com/help/toolbox/ident/ref/arx.html">aquí</a>. <br />
<br />
<blockquote class="tr_bq">
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">% REAL DATA 1: MISSILE<br />load(fullfile(matlabroot, 'toolbox', 'ident', 'iddemos', 'data', 'missiledata.mat'));<br />% o bien: </span></div>
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">% load motorizedcamera<br />data = iddata(y, u);</span>
</div>
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;"><br /></span></div>
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">p = 2;</span></div>
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">outputs = size(y,2);<br />inputs = size(u,2);<br />model = arx(data, [p*ones(outputs, outputs), p*ones(outputs, inputs), ones(outputs, inputs)]);</span> </div>
</blockquote>
<br />Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-1477785295951784932011-12-02T17:03:00.000-08:002011-12-19T17:09:43.691-08:00Video de la Simulación con Actuadores ProgramadosGracias al código Fortran agregado a los loops de simulación del CodeSaturne, pudimos agregar actuadores de plasma a los resultados anteriores.<br />
De esta forma simulamos la actuación en dos sectores del cilindro, realizando pulsaciones de plasma con ángulo de salida tangente para ver la respuesta del sistema. Se espera que las turbulencias del cilindro desaparezcan con el plasma aplicado y vuelvan a generarse tan pronto se retire el efecto del actuador.<br />
Durante esta simulación se agregaron algunos esquemas de actuación periódicos, oscilantes y asiméticos para poder relevar información que será usada en la identificación del sistema mediante el modelo ARX.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dw45Yamf3mtkPvhFb8A9ZMqhp8diFehnXgYkqi9XQAglYweQKfVjz7QlE0nSUC9jNGOg90jin2o02-NIhkNyA' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<br />Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-38541364415077737552011-11-13T09:51:00.001-08:002011-11-13T10:09:04.442-08:00Usando variables 'static' en Fortran para cargar un CSV sólo una vezPara completar la idea de utilizar un vector desde un archivo dentro del código de <b>code saturne</b> es importante dar ciertas garantías de performance. La subrutina a utilizar se encuentra dentro del archivo <b>usclim.f90</b> que es utilizado de forma repetitiva durante la simulación.<br />
<br />
Una forma de garantizar que la carga del CSV se realiza una sóla vez es utilizando código global y variables globales. Lamentablemente, el archivo disponible no cuenta con las secciones comunes con lo que se supone una composición de ese código dentro del programa de simulación general.<br />
<br />
Otra alternativa es utilizar variables en el data segment persistentes entre llamadas a la subrutina. Optamos por ese camino y utilizamos la palabra reservada <b>SAVE</b> para realizar un breve programa de prueba:<br />
<br />
<pre>program read_csv_once
implicit none
call readAndPrint(1000)
call readAndPrint(100)
end program read_csv_once
subroutine readAndPrint(test_offset)
integer:: test_offset
integer, parameter:: values_qty = 2
real, save, pointer:: pValues(:)
logical, save:: pValues_initialized= .false.
if (.not.pValues_initialized) then
allocate(pValues(values_qty))
open(unit=99, file="act1.csv", action="read")
read(99, *) pValues
close(99)
pValues = pValues + test_offset
pValues_initialized = .true.
endif
write(*,*) "Values from file:", pValues
write(*,*) "Values Quantity:", values_qty
end subroutine
</pre>
Nuevamente tenemos una cantidad fija de valores a leer del CSV dado que por el momento es un número conocido.<br />
Notar que el puntero estático pValues NO posee un valor por defecto definido, es por ese motivo que se utiliza pValues_initialized para controlar si se hizo la lectura del CSV o no.<br />
El resultado de correr este programa de pruebas es:<br />
<br />
<pre> Values from file: 1003.6295 1003.6688
Values Quantity: 2
Values from file: 1003.6295 1003.6688
Values Quantity: 2
</pre>
<br />
Demostrando que la inicialización se realizó una vez.<br />
<br />
<br />Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-38402489413690038402011-11-13T09:45:00.001-08:002011-11-13T09:50:26.146-08:00Algo en fortran: leyendo un array desde CSVAnte la preguntá de ¿qué motivos tengo para hacer eso? contesto: necesito levantar un array dinámico desde un archivo para hacer uso de los valores dentro de una simulación con code saturne.<br />
<div>
<br /></div>
<div>
Vamos a un código muy sencillo:</div>
<div>
<br /></div>
<pre><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">program readcsv
implicit none
call readAndPrint()
end program readcsv
subroutine readAndPrint()
integer, parameter:: values_qty = 20
real, pointer:: pValues(:)
allocate(pValues(values_qty))
open(unit=99, file="act1.csv", action="read")
read(99, *) pValues
close(99)
write(*,*) "Values from file:", pValues
write(*,*) "Values Quantity:", values_qty
end subroutine</span></span>
</pre>
<pre><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">
</span></span></pre>
<pre><span class="Apple-style-span" style="font-family: Times;"><span class="Apple-style-span" style="white-space: normal;">La cantidad de valores a leer está fija por el momento. Una posible solución sería hacer una prelectura de la primer fila y contar la cantidad de caracteres ',' para luego hacer una alocación con la cantidad exacta de valores. Otra posibilidad es leer toda la fila y agregarlos al array realocando en cada iteración.</span></span></pre>
<pre><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">
</span></span></pre>Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-42725183832386826472011-11-01T17:01:00.000-07:002011-12-19T17:02:19.638-08:00Primeros Resultados de la SimulaciónLuego de muchas corridas fallidas, donde el mallado de la experiencia y los distintos parámetros numéricos fueron ajustados, llegamos a una corrida limpia de la simulación.<br />
<br />
El CodeSaturne demostró ser un tanto complejo en su puesta a punto pero muy potente y versátil. Permite cálculos simples como la experiencia del cilindro o mucho más complejos usando nociones químicas o de termodinámica.<br />
<br />
En este caso nos limitamos a mostrar unas imágenes del cilindro luego de alcanzar un régimen estacionario respecto de las oscilaciones de la estela. En la imagen se puede notar el desprendimiento de vórtices que se pretende controlar en el sistema de control y para el cual será necesario agregar unos actuadores al mallado del cilindro.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-CwqC_memX0A/Tu_eFbXSoVI/AAAAAAAABN4/u3CzJA80iIM/s1600/step.1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="316" src="http://4.bp.blogspot.com/-CwqC_memX0A/Tu_eFbXSoVI/AAAAAAAABN4/u3CzJA80iIM/s320/step.1.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-7M9iKOq1Klg/Tu_eHcULb3I/AAAAAAAABOA/F6lrY42FzSA/s1600/step.10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="316" src="http://3.bp.blogspot.com/-7M9iKOq1Klg/Tu_eHcULb3I/AAAAAAAABOA/F6lrY42FzSA/s320/step.10.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-6xZOV9wBYt4/Tu_eJGY5CVI/AAAAAAAABOI/rrOQauaFd4o/s1600/step.20.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="318" src="http://1.bp.blogspot.com/-6xZOV9wBYt4/Tu_eJGY5CVI/AAAAAAAABOI/rrOQauaFd4o/s320/step.20.png" width="320" /></a></div>
<br />Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-20328087687566211842011-10-25T16:52:00.000-07:002011-12-19T16:54:37.949-08:00Mallado para Simulación de la ExperienciaA fin de conseguir una simulación realista de la experiencia mediante el uso de <a href="http://tesisingenieriainformatica.blogspot.com/2011/10/code-sature-realizando-una-simulacion.html">Code Saturne</a> armamos un mallado de la experiencia que nos permite definir la simetría en juego. Existen varias herramientas de mallado, optamos por <a href="http://gid.cimne.upc.es/">GiD</a> por la pequeña curva de aprendizaje y la disponibilidad de información dentro del laboratorio. Como agregado este software tiene la posibilidad de hacer simulaciones con y la posibilidad de hacer simulaciones con módulos codificados por colaboradores del laboratorio.<br />
En este caso no utilizaremos GiD para simular o realizar post-procesamiento sino simplemente para el mallado de la experiencia.<br />
La simetría del experimento es muy sencilla y los mallados preliminares no fueron problemáticos. A continuación se incluyen distintos acercamientos de la experiencia, donde se puede observar el cilindro sobre el lado izquierdo dejando buena parte del mallado derecho para la estela que debe producir.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-aK9NZSvkk9w/Tu_bENJnHdI/AAAAAAAABNY/-nF7WCHyyLk/s1600/Malla01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="http://1.bp.blogspot.com/-aK9NZSvkk9w/Tu_bENJnHdI/AAAAAAAABNY/-nF7WCHyyLk/s200/Malla01.png" width="200" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-9puPv4eGrPU/Tu_bZZ86pXI/AAAAAAAABNg/mbJtJfyrTNc/s1600/Malla02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="151" src="http://4.bp.blogspot.com/-9puPv4eGrPU/Tu_bZZ86pXI/AAAAAAAABNg/mbJtJfyrTNc/s320/Malla02.png" width="320" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-3lfAmSLTgIs/Tu_bat5uqLI/AAAAAAAABNo/qdN15UvLwGg/s1600/Malla03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="137" src="http://4.bp.blogspot.com/-3lfAmSLTgIs/Tu_bat5uqLI/AAAAAAAABNo/qdN15UvLwGg/s320/Malla03.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-lDZfhZLpHvc/Tu_bbY0MpmI/AAAAAAAABNw/8YBEks-qrDk/s1600/Malla04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="137" src="http://3.bp.blogspot.com/-lDZfhZLpHvc/Tu_bbY0MpmI/AAAAAAAABNw/8YBEks-qrDk/s320/Malla04.png" width="320" /></a></div>
<br />
<br />
A lo largo de las imágenes se puede observar que el grado de precisión necesario para los nodos del mallado implica una cantidad enorme de nodos. Por otro lado se intenta minimizar la precisión en zonas donde no se requiere gran nitidez durante el procesamiento o el análisis de resultados.<br />
<br />Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-12267779717399554042011-10-10T14:20:00.000-07:002012-06-03T09:55:36.338-07:00Code Saturne: Realizando una simulación numérica del experimentoYa con varias piezas dispuestas para la experiencia del control del cilindro, nos es necesario datos más cercanos a la realidad para probar los módulos por separado. Si bien se podría plantear el experimento y obtener imágenes del mismo, resulta más simple (y flexible) realizar una simulación numérica. A tal efecto, elegimos la librería de código abierto <a href="http://research.edf.com/research-and-the-scientific-community/software/code-saturne/introduction-code-saturne-80058.html">Code Saturne</a>.<br />
<br />
<br />
Dado que la instalación es un tanto tediosa y se lleva a cabo frecuentemente en el laboratorio, creamos una wiki para el laboratorio y tomamos nota de los pasos utilizando el archivo por lotes: install_saturne.py. Para más información, <a href="http://laboratorios.fi.uba.ar/lfd/wiki/doku.php?id=public:instructivos:instalacion_code_saturne">ver aquí</a>.<br />
<br />
La ejecución no deja de ser algo compleja:<br />
<ol>
<li>Se debe definir la experiencia con su simetría y parámetros físicos</li>
<li>Se debe utilizar un programa de mallado para generar la cuadrícula para simular la física elegida. En este caso se utiliza el programa GID.</li>
<li>Se debe correr el sistema de simulación Code Saturne en alguna de sus variantes</li>
<ol>
<li>Mediante el entorno gráfico.</li>
<li>Realizando la configuración por archivos y corriendo el sistema por línea de consola. Esta opción es muy común para poder correr los trabajos de forma remota. Se agrega un instructivo a la flamante wiki del laboratorio. Para más información, <a href="http://laboratorios.fi.uba.ar/lfd/wiki/doku.php?id=public:instructivos:ejecucion_code_saturne">ver aquí</a>.</li>
</ol>
</ol>
<br />
En el proceso nos topamos con un blog muy interesante de un estudiante de fluidodinámica del Reino Unido que vale la pena visitar:<br />
<a href="http://code-saturne.blogspot.com/">http://code-saturne.blogspot.com/</a><br />
<br />
<br />Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-88776560784935435132011-09-17T12:51:00.001-07:002011-11-13T09:43:50.633-08:00Probando el código C/CUDA (o C/C++) usando MatlabDado que comunicar Matlab con el código C/CUDA (o C/C++) no es la principal preocupación para la tesis, se aplica un poca investigación al tema y se implementa rápidamente un protocolo que permite comunicar entradas y salidas. En este caso, la comunicación consta de varias matrices de entrada y varias de salida. En todos los casos se trata de números flotantes.<br />
Para que la ejecución del programa escrito en C sea transparente, se crea una función Matlab con el mismo nombre que el programa C, esta función será la encargada de grabar en disco las variables Matlab, llamar al ejecutable escrito en C, esperar que concluya exitosamente y leer las variables de salida desde el disco.<br />
Las variables en disco se crean en una ubicación definida por el código Matlab (generalmente en una carpeta temporal) y se comunican al programa C mediante argumentos<br />
<br />
Este esquema tiene un payload asociado a la lectura/escritura en disco de las variables que podría evitarse con algún método más directo...<br />
A futuro, se recomienda utilizar la compilación MEX de Matlab:<br />
<a href="http://www.mathworks.com/help/techdoc/matlab_external/f23224.html">http://www.mathworks.com/help/techdoc/matlab_external/f23224.html</a>Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-39689447014050558642011-09-01T00:00:00.000-07:002011-09-22T07:34:49.939-07:00Librerías sobre Operaciones matemáticas en C/C++A la hora de realizar los programas de prueba en C/C++, previo a codificarlos en C/CUDA fue necesario definir ciertas funciones de soporte matemáticas.<br />
<br />
Como todo sistema de operaciones básicas comenzó con una clase Matrix<T> propia, con operaciones simples como multiplicar o sumar. A medida que el sistema creció, fue necesario implementar transposiciones y vistas de columnas o filas de la matriz. En ese punto, y buscando una implementación de inversión de matrices, resultaba obvia la necesidad de buscar un mejor soporte en librerías existentes.<br />
A continuación, una colección de links relacionados:<br />
<br /><ul>
<li>C/C++</li>
<ul>
<li>Gnu Scientific Library, con muchas operaciones y TDAs escritos en C</li>
<ul>
<li><a href="http://www.gnu.org/software/gsl/">http://www.gnu.org/software/gsl/</a></li>
</ul>
</ul>
<ul>
<li>Projectos VS2010 para compilar GSL en Windows: una contribución de Brian Gladman donde se descomprimen los proyectos dentro de la carpeta de descarga del GSL y con una lectura del readme se obtienen las librerías</li>
<ul>
<li><a href="http://gladman.plushost.co.uk/oldsite/computing/gnu_scientific_library.php">http://gladman.plushost.co.uk/oldsite/computing/gnu_scientific_library.php</a></li>
</ul>
</ul>
<ul>
<li>Clase Matrix con operaciones de inversión de Mike Dinolfo</li>
<ul>
<li> <a href="http://users.erols.com/mdinolfo/matrix.htm">http://users.erols.com/mdinolfo/matrix.htm</a></li>
</ul>
</ul>
<ul>
<li>Numerical Recipes, se trata de librerías matemáticas muy usadas y conocidas. Son pagas pero con un bajo costo</li>
<ul>
<li><a href="http://www.nr.com/">http://www.nr.com</a> </li>
</ul>
</ul>
<li>Matlab </li>
<ul>
<li>Utilización de código Matlab desde C/C++</li>
<ul>
<li> <a href="http://www.mathworks.com/help/techdoc/matlab_external/f38569.html">http://www.mathworks.com/help/techdoc/matlab_external/f38569.html</a></li>
</ul>
</ul>
<ul>
<li>Pequeño instructivo para utilizar GSL en Matlab</li>
<ul>
<li><a href="http://www.kellogg.northwestern.edu/faculty/papanikolaou/htm/gsl.htm">http://www.kellogg.northwestern.edu/faculty/papanikolaou/htm/gsl.htm</a></li>
</ul>
</ul>
<li>Python </li>
<ul>
<li>Plataforma para python</li>
<ul>
<li><a href="http://coan.burnham.org/downloads">http://coan.burnham.org/downloads</a></li>
</ul>
</ul>
<ul>
<li>SAGE, otra librería para python</li>
<ul>
<li><a href="http://www.sagenb.org/">http://www.sagenb.org/</a></li>
</ul>
</ul>
</ul>
Luego de evaluar todas las posibilidades, optamos por los dos primeros links: utilizar GSL y realizar una compilación custom para Windows. <br />
<ul>
</ul>
Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-89017713676029536362011-07-14T21:22:00.000-07:002011-07-14T21:22:28.611-07:00Simulando modelos conocidosMatlab provee varias funciones que son de utilidad para simular modelos del tipo SISO, MIMO, etc. Una de las más útiles es <b>sim</b> que, dado un conjunto de datos de entrada y/o salida más un modelo ya definido, aplica el modelo a los datos y retorna la salida ulterior.<div>Veamos un ejemplo:</div><span class="Apple-style-span" style="font-size: x-small;"><blockquote><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-family: Times;"><br />
</span></span></blockquote><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><blockquote>%genero un modelo según y(n) = u(n) - 2u(n-1)</blockquote><blockquote>A = [1] ; B = [1 -2];</blockquote><blockquote>modelo = idpoly(A, B);</blockquote><blockquote><br />
</blockquote><blockquote>%genero los datos para la simulación:</blockquote><blockquote>% ejemplos:</blockquote><blockquote>% iddata([], [1:100]') para salida nula y entrada del 1 al 100</blockquote><blockquote>% iddata([], idinput(100)) para salida nula y entrada aleatoria -1;1</blockquote><blockquote>data = iddata([],[1:10]');</blockquote><blockquote><br />
</blockquote><blockquote>%simulo</blockquote><blockquote>simulacion = sim(modelo, data);</blockquote><blockquote>plot(simulacion.y);</blockquote></span></span><div><br />
</div><div>Bastante sencillo, si se cuenta con los datos de entrada e información sobre el modelo podemos calcular rápidamente la salida. </div><div>Obviamente, se pueden aplicar relaciones mucho más complejas cambiando los coeficientes de A y B. Tanto es así que son esos vectores los que definen la transferencia G(s) que relaciona Y(s) y U(s) (salida con entrada). Entonces, el numerador evaluado en el operador de regresión <b>q</b> se convierte en A(q) mientras que el denominador hace lo propio en B(q). Si observamos con atención, podemos ver esa información en la variable <b>modelo</b>:</div><div><blockquote><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">>> modelo</span></span></blockquote><blockquote><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">Discrete-time IDPOLY model: y(t) = B(q)u(t) + e(t)</span></span></blockquote><blockquote><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">B(q) = 1 - 2 q^-1 </span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> </span></blockquote><blockquote><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">This model was not estimated from data. </span></span></blockquote><blockquote><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">Sampling interval: 1 </span></span></blockquote></div>Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-80857130899403550132011-06-15T07:28:00.000-07:002011-06-24T07:50:31.601-07:00Y dónde está cutil64.dll??Muchos de los ejemplos que circulan por internet utilizan esta DLL. Tiene utilitarios generales para CUDA y viene dentro del "GPU Computing SDK examples". Para facilitar las cosas, es conveniente tomar esa librería (la versión correcta y para la plataforma correcta) de su carpeta en el SDK y colocarla dentro de la carpeta de instalación de CUDA. Lo mismo ocurre con los correspondientes archivos .lib.<br />
Entonces, para un sistema 64 bits, copiamos:<br />
<ul><li><NVIDIA GPU Computing SDK Folder>\C\inc\cutil.h en <CUDA Folder>\include</li>
<li><NVIDIA GPU Computing SDK Folder>\C\bin\win64\Release\cutil64.dll en <CUDA Folder>\bin64</li>
<li><NVIDIA GPU Computing SDK Folder>\C\bin\win64\Debug\cutil64D.dll en <CUDA Folder>\bin64</li>
<li><NVIDIA GPU Computing SDK Folder>\C\common\lib\cutil64.lib en <CUDA Folder>\lib64</li>
<li><NVIDIA GPU Computing SDK Folder>\C\common\lib\cutil64D.lib en <CUDA Folder>\lib64</li>
</ul>A modo anecdótico, dejo unos comentarios sobre la cutil.dll del release notes de una versión de CUDA:<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> - Most samples link to a utility library called "cutil" whose source code</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> is in "NVIDIA CUDA SDK\common". The release and emurelease versions of</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> these samples link to cutil[32|64].lib and dynamically load</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> cutil[32|64].dll. The debug and emudebug versions of these samples link</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> to cutil[32D|64D].lib and dynamically load cutil[32D|64D].dll.</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> To build the 32-bit and/or 64-bit, release and/or debug configurations</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> of the cutil library, use the solution files located in</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> "NVIDIA CUDA SDK\common". The output of the compilation goes to</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> "NVIDIA CUDA SDK\common\lib":</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> - cutil[32|64].lib and cutil[32D|64D].lib are the release and debug</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> import libraries,</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> - cutil[32|64].dll and cutil[32D|64D].dll are the release and debug</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> dynamic-link libraries, which get also copied to</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> "NVIDIA CUDA SDK\bin\win[32|64]\[release|emurelease]" and</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> "NVIDIA CUDA SDK\bin\win[32|64]\[debug|emudebug]"</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> respectively;</span></span>Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-90903137178824741172011-06-13T22:38:00.000-07:002011-06-15T06:34:40.000-07:00Volviendo el tiempo atrás... CUDA 2.3Lamentablemente, y aunque la sintaxis de CUDA 4 está muy buena, debemos volver a la versión 2.3 sobre Windows y compilar el código del Onera [1] con una resolución del Lucas-Kanade en GPU.<br />
<br />
Lamentablemente, como suele suceder, aparecen nuevos problemas a salvar:<br />
<ul><li>NVCC sin un compilador no funciona. Necesitamos el Visual Studio...</li>
<li>Visual Studio 2008 Express no tiene soporte para procesadores x64 con lo que hay que optar por una versión Trial del Professional.</li>
<li>Para compilar por línea de comandos nos quedamos con un ejemplo pequeño de archivo .cu y logramos compilarlo sólo luego de leer un post interesante [2] en el foro de nvidia: es necesario ejecutar un batch que setea el entorno del VS en modo amd64 y luego indicar algunos parámetros extras al NVCC. </li>
<li>Dentro del VS2008, NVCC sigue sin compilar. Es necesario actualizar el archivo nvcc.profile para que tenga un include extra del visual:</li>
</ul><blockquote style="font-family: "Courier New",Courier,monospace;">INCLUDES += "-I$(TOP)/include" "-I$(TOP)/include/cudart" "-IC:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/include" $(_SPACE_) </blockquote><br />
[1] <a href="http://www.onera.fr/dtim-en/gpu-for-image/folkigpu.php%20">Onera - FOLKI GPU</a><br />
[2] <a href="http://forums.nvidia.com/index.php?showtopic=104811">Post compilación x64</a>Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-58680934190325465852011-06-10T22:32:00.000-07:002011-06-14T22:40:57.256-07:00Eligiendo la cámara - ConclusionesGanador momentaneo: PixelFly<br />
<br />
Conclusiones generales:<br />
<ol><li>La Pulnix es demasiado lenta. Además no ofrece ninguna ventaja significativa.</li>
<li>La PixelFly tiene un buen tiempo de transmisión con binning activado. Según las pruebas de concepto se obtendrían 10 ms entre frame y frame con lo cual se puede usar esta cámara.</li>
<li>La PixelFly tiene además modo de doble shutter que no fue analizado pero brinda más alternativas.</li>
<li>La SpeedCam, aún siendo la de mejor calidad y velocidad no tuvo buenos resultados. La transferencia resulta muy lenta con lo que queda descartada por el momento.</li>
<li>Es importante aclarar que el análisis se basa en la necesidad de hacer un algoritmo lo más veloz posible y poder realiar cálculos en el momento. En caso de no ser esto así se puede reconsiderar los resultados y optar por la SpeedCam en lugar de la PixelFly, por ejemplo. Esto podría ocurrir en caso que se necesite tiempo extra para realizar procesamiento, no requerir 1 frame cada 10 ms sino 2 frames espaciados en 10 ms para, más tarde, repetir la toma de fotos y el proceso.</li>
</ol>Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-46954954493369162132011-06-04T21:42:00.000-07:002011-06-14T21:59:40.173-07:00Tiempos - Usando la SpeedCam programáticamenteEn este punto, la experiencia se convirtió en algo bastante pesado. La SpeedCam no tiene una API de acceso programática. Tampoco permite sacar fotogramas de forma unitaria, sólo se puede sacar una ráfaga que es almacenada en el buffer interno de la cámara y luego transmitido a la PC.<br />
La cámara posee código hecho en Java del cual se pueden obtener los .jar para emplearlos en un código de prueba. <br />
Consultamos entonces a los fabricantes: nos responden que la compañía cambió de manos. Consultamos a los nuevos responsables y obtenemos como información que tenemos tres caminos:<br />
<ul><li>utilizar una API a nivel registro con la cual se accede a la cámara enviando códigos de operación</li>
<li>revisar los archivos minivis.jar y minivis.dll</li>
<li>comprar otra cámara o adquirir el nuevo software.</li>
</ul>Obviamente nos quedamos con la segunda por "simplicidad" (si es que se puede decir que esto sea simple). Entonces, armamos un archivo .Java y tratamos de adivinar cómo se usa la API que contiene el .jar.<br />
Luego de varios días de revisar los resultados del <a href="http://java.decompiler.free.fr/">Java Decompiler</a>. Obtenemos una sucesión de pasos que permite obtener las imágenes con resultados bastante malos:<br />
<ul><li> Snapshots tomados: 200</li>
<li>fps entre Snapshots: 2500 </li>
<li>Tiempo Total: 7800ms (sólo en la transferencia, ya que la toma de imágenes se debe hacer previa a la este paso) </li>
<li>Tiempo Promedio: 39ms (es decir, 25 fps)</li>
</ul>Conclusión: muy mala velocidad para una cámara tan potente. Claramente, no está optimizada para utilizarla de forma programática en entornos real-time. Por el contrario, el buffer parece consumir mucho tiempo de la transferencia.<br />
Pero entonces surge una duda ¿Y si los tiempos son lentos por estar utilizando java? Para tratar de falsear esta teoría, recurrimos a código C++ que intente levantar las DLLs directamente y no utilizar minivis.jar. Nuevamente tenemos que decompilar, en este caso decompilamos el archivo minivis.dll y hacemos un matcheo contra lo observado en minivis.jar. Igualmente, debemos notar que ambos archivos se comunican gracias a que se empleó JNI en C++. Lamentablemente esto simplemente complica la tarea de decompilación y reuso de la DLL original.<br />
Con una sola prueba de concepto nos queda claro que ese no es el mejor camino:<br />
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: Consolas, "Courier New", Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style><br />
<blockquote><pre class="csharpcode">Run-Time Check Failure #0 - The <span class="kwrd">value</span> of ESP was not properly saved across a function call. This <span class="kwrd">is</span> usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention
</pre></blockquote><br />
Aquí el código Java:<br />
<br />
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: Consolas, "Courier New", Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style><br />
<div class="csharpcode"><pre><span class="lnum"> 1: </span><span class="kwrd">class</span> DummyConsumer implements CallbackConsumer {</pre><pre><span class="lnum"> 2: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> modeChanged(<span class="kwrd">int</span> paramInt){</pre><pre><span class="lnum"> 3: </span> }</pre><pre><span class="lnum"> 4: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> statusChanged(<span class="kwrd">int</span> paramInt) {</pre><pre><span class="lnum"> 5: </span> }</pre><pre><span class="lnum"> 6: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> shutterChanged(boolean paramBoolean, <span class="kwrd">short</span> paramShort) {</pre><pre><span class="lnum"> 7: </span> }</pre><pre><span class="lnum"> 8: </span>}</pre><pre><span class="lnum"> 9: </span> </pre><pre><span class="lnum"> 10: </span><span class="kwrd">public</span> <span class="kwrd">class</span> Application {</pre><pre><span class="lnum"> 11: </span> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> main(String[] arguments) {</pre><pre><span class="lnum"> 12: </span> <span class="kwrd">int</span> numberOfImages = Integer.parseInt(arguments[0]);</pre><pre><span class="lnum"> 13: </span> </pre><pre><span class="lnum"> 14: </span> MinivisFactory factory = MinivisFactory.getInstance();</pre><pre><span class="lnum"> 15: </span> <span class="kwrd">try</span> {</pre><pre><span class="lnum"> 16: </span> factory.discover();</pre><pre><span class="lnum"> 17: </span> TypedNetAddress[] addresses = factory.getKnownDevices();</pre><pre><span class="lnum"> 18: </span> String mac = addresses.length > 0 ? addresses[0].getEntryName() : <span class="str">"00-50-C2-1D-7E-AB"</span>;</pre><pre><span class="lnum"> 19: </span> DummyConsumer callbackConsumer = <span class="kwrd">new</span> DummyConsumer();</pre><pre><span class="lnum"> 20: </span> Proxy camera = factory.getCamera(mac, callbackConsumer);</pre><pre><span class="lnum"> 21: </span> <span class="kwrd">try</span> {</pre><pre><span class="lnum"> 22: </span> camera.connect();</pre><pre><span class="lnum"> 23: </span> <span class="kwrd">try</span> {</pre><pre><span class="lnum"> 24: </span> takeSnapshots(camera, numberOfImages, debug);</pre><pre><span class="lnum"> 25: </span> } </pre><pre><span class="lnum"> 26: </span> <span class="kwrd">finally</span> {</pre><pre><span class="lnum"> 27: </span> camera.disconnect();</pre><pre><span class="lnum"> 28: </span> }</pre><pre><span class="lnum"> 29: </span> }</pre><pre><span class="lnum"> 30: </span> <span class="kwrd">finally</span> {</pre><pre><span class="lnum"> 31: </span> camera.release();</pre><pre><span class="lnum"> 32: </span> }</pre><pre><span class="lnum"> 33: </span> }</pre><pre><span class="lnum"> 34: </span> <span class="kwrd">catch</span>(Exception e) {</pre><pre><span class="lnum"> 35: </span> e.printStackTrace();</pre><pre><span class="lnum"> 36: </span> }</pre><pre><span class="lnum"> 37: </span> }</pre><pre><span class="lnum"> 38: </span> <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> takeSnapshots(Proxy camera, <span class="kwrd">int</span> numberOfImages, boolean debug) throws IOException, MDriverException, Exception {</pre><pre><span class="lnum"> 39: </span> camera.setMode(4); <span class="rem">//0 LIVE 1 RECORD 2 TRIGGERED 3 DRAM 4 LOWLIGHT</span></pre><pre><span class="lnum"> 40: </span> camera.trigger();</pre><pre><span class="lnum"> 41: </span> </pre><pre><span class="lnum"> 42: </span> <span class="rem">//missing code here: wait for trigger to finish</span></pre><pre><span class="lnum"> 43: </span> </pre><pre><span class="lnum"> 44: </span> MFrameInfo frameInfo = <span class="kwrd">new</span> MFrameInfo();</pre><pre><span class="lnum"> 45: </span> <span class="kwrd">for</span>(<span class="kwrd">int</span> i = 0; i < numberOfImages; ++i) {</pre><pre><span class="lnum"> 46: </span> <span class="kwrd">byte</span>[] frameBytes = camera.getFrame(-1, -1 , frameInfo);</pre><pre><span class="lnum"> 47: </span> }</pre><pre><span class="lnum"> 48: </span> }</pre><pre><span class="lnum"> 49: </span>}</pre></div><br />
Aquí el código C++:<br />
<br />
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: Consolas, "Courier New", Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style><br />
<div class="csharpcode"><pre><span class="lnum"> 1: </span> </pre><pre><span class="lnum"> 2: </span>#include <span class="str">"stdafx.h"</span></pre><pre><span class="lnum"> 3: </span>#include <iostream></pre><pre><span class="lnum"> 4: </span> </pre><pre><span class="lnum"> 5: </span> </pre><pre><span class="lnum"> 6: </span><span class="kwrd">int</span> _tmain(<span class="kwrd">int</span> argc, _TCHAR* argv[])</pre><pre><span class="lnum"> 7: </span>{</pre><pre><span class="lnum"> 8: </span> HMODULE hMod = LoadLibrary(<span class="str">"minivis.dll"</span>);</pre><pre><span class="lnum"> 9: </span> typedef <span class="kwrd">long</span> (*MinivisFactory_Create)();</pre><pre><span class="lnum"> 10: </span> typedef <span class="kwrd">long</span> (*GetCamera)(<span class="kwrd">long</span>, <span class="kwrd">char</span>*, <span class="kwrd">void</span>*);</pre><pre><span class="lnum"> 11: </span> MinivisFactory_Create n_MinivisFactory_Create = (MinivisFactory_Create)GetProcAdress(<span class="str">"_Java_com_artho_visart_plugins_minivis_internal_jni_MinivisFactory_n_1MinivisFactory_1Create@8"</span>);</pre><pre><span class="lnum"> 12: </span> GetCamera n_GetCamera = (GetCamera)GetProcAdress(<span class="str">"_Java_com_artho_visart_plugins_minivis_internal_jni_MinivisFactory_n_1GetCamera@24"</span>);</pre><pre><span class="lnum"> 13: </span> </pre><pre><span class="lnum"> 14: </span> </pre><pre><span class="lnum"> 15: </span> <span class="kwrd">long</span> adapterPtr = n_MinivisFactory_Create();</pre><pre><span class="lnum"> 16: </span> <span class="kwrd">void</span>* consumer = NULL;</pre><pre><span class="lnum"> 17: </span> <span class="kwrd">long</span> pointer = n_GetCamera(adapterPtr, <span class="str">"00-50-C2-1D-7E-AB"</span>, consumer);</pre><pre><span class="lnum"> 18: </span> </pre><pre><span class="lnum"> 19: </span> std::cout << <span class="str">"Camera pointer:"</span> << pointer << std::endl;</pre><pre><span class="lnum"> 20: </span> std::cout << <span class="str">"Press any key to continue..."</span> << std::endl;</pre><pre><span class="lnum"> 21: </span> <span class="kwrd">char</span> character;</pre><pre><span class="lnum"> 22: </span> std::cin >> character;</pre><pre><span class="lnum"> 23: </span> <span class="kwrd">return</span> 0;</pre><pre><span class="lnum"> 24: </span>}</pre></div>Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-58907644872210353892011-05-30T21:31:00.000-07:002011-06-14T21:32:26.805-07:00Tiempos - Usando la PixelFly programáticamenteSimilar al caso de la Pulnix, se escribe código usando la API provista para PixelFly y se miden los tiempos aproximados. En este caso se cuenta con dos APIs a utilizar: la original de la cámara (para VC++) y un SDK unificado para las PixelFly y las Sensicam llamado <a href="http://www.pco.de/software/pixelfly-qe/">Uniform SDK</a>. Se opta por el último por tener una interfaz más clara y no requerir elementos de WinApi para funcionar; según la documentación esta interfaz es más lenta que la original, pero igualmente sirve para computar órdenes de magnitud. <br />
<br />
Resultados:<br />
<ul><li> Snapshots tomados: 200</li>
<li>fps entre Snapshots: 50 </li>
<li>Tiempo Total: 4000ms </li>
<li>Tiempo Promedio: 20 ms (es decir, 50 fps)</li>
</ul>Misma conclusión que la obtenida con la Pulnix: transferencia despreciable. Igualmente seguimos teniendo el doble del tiempo previsto para la toma de fotos.<br />
Afortunadamente, la PixelFly presenta una opción de <a href="http://en.wikipedia.org/wiki/Data_binning">binning</a> que puede reducir los tiempos empleados. El binning consiste en realizar algún procesamiento sobre un conjunto de píxeles y generar un único píxel que contiene información de los anteriores. En el común de los casos la operación consiste en promediar los valores.<br />
Los nuevos resultados:<br />
<br />
<ul><li> Snapshots tomados: 200</li>
<li>fps entre Snapshots: ? </li>
<li>Tiempo Total: 2000ms </li>
<li>Tiempo Promedio: 10 ms (es decir, 100 fps)</li>
</ul> Conclusión: ya tenemos el tiempo que queríamos !!<br />
Al parecer el binning permite incluso que la cámara tome fotografías en una frecuencia más alta. Queda pendiente evaluar la capacidad de double shutter.<br />
<ul></ul>Aquí el código:<br />
<br />
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: Consolas, "Courier New", Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style><br />
<div class="csharpcode"><pre><span class="lnum"> 1: </span><span class="preproc">#define</span> GAIN 1</pre><pre><span class="lnum"> 2: </span><span class="preproc">#define</span> DELAY 0 <span class="rem">//ms</span></pre><pre><span class="lnum"> 3: </span><span class="preproc">#define</span> EXPOSURE_TIME 5 <span class="rem">//ms</span></pre><pre><span class="lnum"> 4: </span><span class="preproc">#define</span> ROIX 2 <span class="rem">//from 1 to 20</span></pre><pre><span class="lnum"> 5: </span><span class="preproc">#define</span> ROIY 2 <span class="rem">//from 1 to 20</span></pre><pre><span class="lnum"> 6: </span> </pre><pre><span class="lnum"> 7: </span><span class="kwrd">int</span> main(<span class="kwrd">int</span> argc, <span class="kwrd">char</span>* argv[]) {</pre><pre><span class="lnum"> 8: </span> <span class="kwrd">int</span> totalSnapshots;</pre><pre><span class="lnum"> 9: </span> std::cout << <span class="str">"Qty of snapshots to take: "</span>;</pre><pre><span class="lnum"> 10: </span> std::cin >> totalSnapshots;</pre><pre><span class="lnum"> 11: </span> </pre><pre><span class="lnum"> 12: </span> <span class="kwrd">int</span> camId;</pre><pre><span class="lnum"> 13: </span> CAMINFO camData[8];</pre><pre><span class="lnum"> 14: </span> </pre><pre><span class="lnum"> 15: </span> <span class="kwrd">int</span> boardNumber = 0;</pre><pre><span class="lnum"> 16: </span> <span class="kwrd">int</span> error;</pre><pre><span class="lnum"> 17: </span> <span class="kwrd">if</span> (error = SELECT_CAMERA(<span class="str">"pixelfly"</span>, boardNumber, &camId, camData))</pre><pre><span class="lnum"> 18: </span> showErrorAndClose(error);</pre><pre><span class="lnum"> 19: </span> <span class="kwrd">else</span> {</pre><pre><span class="lnum"> 20: </span> <span class="kwrd">if</span> (error = SETUP_CAMERA(camId, camData, 0, 0, 0, 1, ROIX, 1, ROIY, 1, 1, GAIN, DELAY, EXPOSURE_TIME))</pre><pre><span class="lnum"> 21: </span> showErrorAndClose(error);</pre><pre><span class="lnum"> 22: </span> <span class="kwrd">else</span> { </pre><pre><span class="lnum"> 23: </span> time_t beginTime, endTime;</pre><pre><span class="lnum"> 24: </span> time(&beginTime);</pre><pre><span class="lnum"> 25: </span> </pre><pre><span class="lnum"> 26: </span> <span class="kwrd">int</span> snapshotNumber = 0;</pre><pre><span class="lnum"> 27: </span> <span class="kwrd">while</span> (! error && snapshotNumber < totalSnapshots) {</pre><pre><span class="lnum"> 28: </span> <span class="kwrd">if</span> (error = SNAP(camId, camData, 0))</pre><pre><span class="lnum"> 29: </span> showErrorAndClose(error);</pre><pre><span class="lnum"> 30: </span> <span class="kwrd">else</span> {</pre><pre><span class="lnum"> 31: </span> <span class="kwrd">if</span> (error = GETIMAGE(camId, camData, 2000))</pre><pre><span class="lnum"> 32: </span> showErrorAndClose(error);</pre><pre><span class="lnum"> 33: </span> <span class="kwrd">else</span> </pre><pre><span class="lnum"> 34: </span> <span class="rem">// image in memory at this point</span></pre><pre><span class="lnum"> 35: </span> }</pre><pre><span class="lnum"> 36: </span> snapshotNumber++;</pre><pre><span class="lnum"> 37: </span> }</pre><pre><span class="lnum"> 38: </span> time(&endTime);</pre><pre><span class="lnum"> 39: </span> std::cout << std::endl << <span class="str">"Tiempo Promedio por imagen: "</span> << 1000.0 * (<span class="kwrd">double</span>)difftime(endTime, beginTime) / (<span class="kwrd">float</span>)totalSnapshots << <span class="str">"ms."</span> << std::endl;</pre><pre><span class="lnum"> 40: </span> }</pre><pre><span class="lnum"> 41: </span> CLOSE_CAMERA(camId, camData);</pre><pre><span class="lnum"> 42: </span> }</pre><pre><span class="lnum"> 43: </span> <span class="kwrd">return</span> 0;</pre><pre><span class="lnum"> 44: </span>}</pre></div>Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-34144998499099718632011-05-25T21:09:00.000-07:002011-06-14T21:10:16.136-07:00Tiempos - Usando la Pulnix programáticamenteCódigo feo... necesitamos saber si el tiempo de transferencia de la Pulnix con la placa adquisidora es suficiente para alcanzar los 100 fps.<br />
Usamos la API de Imagenation (muy vieja pero efectiva). Sacamos N snapshots y medimos el tiempo entre cada una de ellas usando <span style="font-family: "Courier New",Courier,monospace;">time()</span>.<br />
Resultados:<br />
<ul><li> Snapshots tomados: 120</li>
<li>fps entre Snapshots: 30 </li>
<li>Tiempo Total: 4000ms </li>
<li>Tiempo Promedio: 33.3ms (es decir, 30 fps)</li>
</ul><br />
Conclusión: el tiempo de transferencia es despreciable o bien se compenza con el tiempo de toma de la próxima foto.<br />
<br />
Aquí un snippet del código:<br />
<br />
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: Consolas, "Courier New", Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style><br />
<div class="csharpcode"><pre><span class="lnum"> 1: </span><span class="kwrd">int</span> main(<span class="kwrd">int</span> argc, <span class="kwrd">char</span>* arg[])</pre><pre><span class="lnum"> 2: </span>{</pre><pre><span class="lnum"> 3: </span> PXD pxd;</pre><pre><span class="lnum"> 4: </span> FRAMELIB frameLib;</pre><pre><span class="lnum"> 5: </span> <span class="kwrd">long</span> hFG=0;</pre><pre><span class="lnum"> 6: </span> <span class="kwrd">char</span> arcFileName[20];</pre><pre><span class="lnum"> 7: </span> <span class="kwrd">static</span> <span class="kwrd">int</span> num=0;</pre><pre><span class="lnum"> 8: </span> </pre><pre><span class="lnum"> 9: </span> <span class="kwrd">int</span> NO_FRAMES;</pre><pre><span class="lnum"> 10: </span> std::cout << <span class="str">"Ingrese el Nro de imágenes a capturar (30 fps)"</span>; std::cin >> NO_FRAMES;</pre><pre><span class="lnum"> 11: </span> </pre><pre><span class="lnum"> 12: </span> imagenation_OpenLibrary(<span class="str">"PXD_32.DLL"</span>, &pxd, <span class="kwrd">sizeof</span>(PXD));</pre><pre><span class="lnum"> 13: </span> imagenation_OpenLibrary (<span class="str">"frame_32.dll"</span>, &frameLib, <span class="kwrd">sizeof</span>(FRAMELIB));</pre><pre><span class="lnum"> 14: </span> </pre><pre><span class="lnum"> 15: </span> </pre><pre><span class="lnum"> 16: </span> <span class="rem">//"tm-9701 progressive free-run.cam";</span></pre><pre><span class="lnum"> 17: </span> <span class="kwrd">char</span> configFile[] = {<span class="str">"C:\\PXD\\bin\\default.cam"</span>};</pre><pre><span class="lnum"> 18: </span> hFG= pxd.AllocateFG (-1);</pre><pre><span class="lnum"> 19: </span> </pre><pre><span class="lnum"> 20: </span> CAMERA_TYPE *configInMem = pxd.LoadConfig(configFile);</pre><pre><span class="lnum"> 21: </span> pxd.SetCameraConfig(hFG,configInMem);</pre><pre><span class="lnum"> 22: </span> pxd.FreeConfig(configInMem);</pre><pre><span class="lnum"> 23: </span> time_t beginTime, endTime;</pre><pre><span class="lnum"> 24: </span> printf(<span class="str">"Inicio de Captura %d imagenes \n\n"</span>,NO_FRAMES);</pre><pre><span class="lnum"> 25: </span> time(&beginTime);</pre><pre><span class="lnum"> 26: </span> <span class="kwrd">for</span>(num= 0; num {</pre><pre><span class="lnum"> 27: </span> time(&captureTime);</pre><pre><span class="lnum"> 28: </span> FRAME* pFRAME = pFRAME = pxd.AllocateBufferList (pxd.GetWidth(hFG), pxd.GetHeight(hFG), pxd.GetPixelType(hFG), 1 <span class="rem">/*solo un frame*/</span>);</pre><pre><span class="lnum"> 29: </span> pxd.Grab (hFG, pFRAME,IMMEDIATE);</pre><pre><span class="lnum"> 30: </span> sprintf(arcFileName,<span class="str">"30fps%.3d.bmp"</span>, num);</pre><pre><span class="lnum"> 31: </span> frameLib.ExtractPlane(pFRAME,1);</pre><pre><span class="lnum"> 32: </span> <span class="rem">//frameLib.WriteBMP ( frameLib.ExtractPlane(pFRAME,1), arcFileName,1);</span></pre><pre><span class="lnum"> 33: </span> frameLib.FreeFrame (pFRAME);</pre><pre><span class="lnum"> 34: </span> }</pre><pre><span class="lnum"> 35: </span> </pre><pre><span class="lnum"> 36: </span> time(&endTime);</pre><pre><span class="lnum"> 37: </span> std::cout << std::endl << <span class="str">"Tiempo Promedio por imagen: "</span> << 1000.0 * (<span class="kwrd">double</span>)difftime(endTime, beginTime) / (<span class="kwrd">float</span>)NO_FRAMES << <span class="str">"ms."</span> << std::endl;</pre><pre><span class="lnum"> 38: </span> pxd.FreeFG (hFG);</pre><pre><span class="lnum"> 39: </span> <span class="kwrd">return</span> 0;</pre><pre><span class="lnum"> 40: </span>}</pre><pre><span class="lnum"> 41: </span> </pre><pre><span class="lnum"> 42: </span> </pre></div>Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-8153737731634171142011-05-04T22:05:00.000-07:002011-06-01T21:19:50.611-07:00Eligiendo la cámaraComo ya se comentó, es necesario tomar imágenes del sistema bajo estudio para realizar ciertos chequeos y de esa forma alimentar al lazo cerrado. Por lo tanto, el siguente paso será realizar mediciones mediante las distíntas cámaras que se poseen en el laboratorio. Como siempre, realizamos una tabla comparativa:<br />
<br />
<table border="1"><tbody>
<tr> <th>Nombre</th> <th>Tipo</th> <th>Resolución Max</th> <th>FPS</th> <th>Cropping / ROI</th> <th>Buffer / Tipo de Transferencia</th> <th>Url</th> </tr>
<tr> <td>PXD Frame Grabber Family - Cyber Optics</td> <td>Placa Adq.</td> <td><span style="font-family: Arial, Helvetica, sans-serif;">32Kx32K </span></td> <td>160 (512x512 con 32bits)</td> <td>Si</td> <td>Interfaz propietaria</td> <td><a href="http://www.imagenation.com/pxdfamily.html">Link</a></td> </tr>
<tr> <td>PixelFly qe - Cooke Coroporation</td> <td>Cámara</td> <td>640x480</td> <td>50</td> <td>Si</td> <td>Sin buffer. Transf. directa por RJ45 en placa Adq. propietaria</td> <td><a href="http://www.cookecorp.com/drivers/pixelfly-qe">Link</a></td> </tr>
<tr> <td>SpeedCam Mini Vis e2 - Weinberger</td> <td>Cámara</td> <td>512x512</td> <td>2500</td> <td>Si</td><td>2GB buffer. Luego Transf. por placa Ethernet 1 Gbit</td> <td><a href="http://www.hsvision.de/en/products/24-minivis-e2.html">Link</a></td> </tr>
<tr> <td>TM-9701 - Pulnix</td> <td>Cámara</td> <td>768x484</td> <td>30</td> <td>No</td> <td>Sin buffer. Transf. directa por placa Adq. PXD</td> <td><a href="http://www.jai.com/SiteCollectionDocuments/Camera_Solutions_Datasheets/TM-Datasheets/Datasheet_TM-9701_screen.pdf">Link</a></td> </tr>
</tbody></table><br />
Si bien la SpeedCam Minivis es la mejor cámara de las tres disponibles, la mejor opción siempre depende de las características que se necesiten.<br />
<br />
En nuestro caso particular son:<br />
<br />
<ol><li>Debe ser programable.</li>
<li>Se necesitan frames con una Dif. de tiempo menor a 10ms. Es decir, 100 fps.</li>
<li>Si bien la Dif. entre frames debe ser menor a 10ms, se puede aceptar un tiempo de transferencia un tanto mayor pero que permita procesar frames de a pares, retornar respuesta al sistema y volver a pedir un par de frames.</li>
<li>Tanto la luminosidad como la resolución no son factores importantes.</li>
</ol><div>Lamentablemente, los puntos 1 a 3 deben ser confirmados empíricamente con lo cual se demora la elección hasta tener información en el campo práctico sobre todas las cámaras.</div>Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-90268264974299538132011-04-26T21:57:00.000-07:002011-05-03T06:41:59.619-07:00Placa más computadora instaladas y funcionandoYa está la placa GTX570 funcionando en un Ubuntu. Posiblemente sea necesario realizar la instalación para Windows dado que muchos de los sensores y actuadores se comunican usando drivers propietarios de Windows.<br />
<div><br />
</div><div>Se instaló CUDA Tools y Toolkit versión 4.0 (release candidate 2, mejor arrancar con el soft de vanguardia dado que lo tienen casi en una versión productiva) junto con el GPU SDK examples de Nvidia (<a href="http://developer.nvidia.com/cuda-toolkit-40#Linux">ver</a>).</div><div><br />
</div><div><br />
<span class="Apple-style-span" style="font-size: large; font-weight: bold;">Linux</span></div><div>Luego de instalar todos los paquetes necesarios (libgl1-mesa-dev, libgl1-mesa-dri, libglu-mesa-dev, freeglut3-dev, libxmu-dev, libxi-dev, etc) y de instalar/reinstalar los drivers y toolkits de Nvidia varias veces llegamos a la primera compilación. Obviamente se trata de ejemplos pre-armados, dentro del SDK. Compilamos y corremos algunos tests como deviceQuery y bandwidthTest:</div><div><br />
</div><div>cd ~/workspace/NVIDIA_GPU_Computing_SDK</div><div>make</div><div>cd C/bin/linux/release</div><div>./deviceQuery</div><div><br />
</div><blockquote><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">./deviceQuery Starting...</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 14.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> CUDA Device Query (Runtime API) version (CUDART static linking)</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 14.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">There is 1 device supporting CUDA</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 14.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">Device 0: "GeForce GTX 570"</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> CUDA Driver Version / Runtime Version 4.0 / 4.0</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> CUDA Capability Major/Minor version number: 2.0</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Total amount of global memory: 1279 MBytes (1341325312 bytes)</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> (15) Multiprocessors x (32) CUDA Cores/MP: 480 CUDA Cores</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> GPU Clock Speed: 1.57 GHz</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Memory Clock rate: 2100.00 Mhz</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Memory Bus Width: 320-bit</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> L2 Cache Size: 655360 bytes</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Max Texture Dimension Size (x,y,z) 1D=(65536), 2D=(65536,65535), 3D=(2048,2048,2048)</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Max Layered Texture Size (dim) x layers 1D=(16384) x 2048, 2D=(16384,16384) x 2048</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Total amount of constant memory: 65536 bytes</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Total amount of shared memory per block: 49152 bytes</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Total number of registers available per block: 32768</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Warp size: 32</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Maximum number of threads per block: 1024</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Maximum sizes of each dimension of a block: 1024 x 1024 x 64</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Maximum sizes of each dimension of a grid: 65535 x 65535 x 65535</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Maximum memory pitch: 2147483647 bytes</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Texture alignment: 512 bytes</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Concurrent copy and execution: Yes with 1 copy engine(s)</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Run time limit on kernels: No</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Integrated GPU sharing Host Memory: No</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Support host page-locked memory mapping: Yes</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Concurrent kernel execution: Yes</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Alignment requirement for Surfaces: Yes</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Device has ECC support enabled: No</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Device is using TCC driver mode: No</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Device supports Unified Addressing (UVA): Yes</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Device PCI Bus ID / PCI location ID: 3 / 0</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Compute Mode:</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> < Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) ></span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 14.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 4.0, CUDA Runtime Version = 4.0, NumDevs = 1, Device = GeForce GTX 570</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">[./deviceQuery] test results...</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">PASSED</span></span></div><div><br />
</div></blockquote><div>./bandwidthTest</div><div><br />
</div><br />
<blockquote><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">./bandwidthTest Starting...</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 14.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">Running on...</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 14.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> Device 0: GeForce GTX 570</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> Quick Mode</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 14.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> Host to Device Bandwidth, 1 Device(s), Paged memory</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> Transfer Size (Bytes)</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">Bandwidth(MB/s)</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> 33554432</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">2961.9</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 14.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> Device to Host Bandwidth, 1 Device(s), Paged memory</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> Transfer Size (Bytes)</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">Bandwidth(MB/s)</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> 33554432</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">2753.8</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 14.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> Device to Device Bandwidth, 1 Device(s)</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> Transfer Size (Bytes)</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">Bandwidth(MB/s)</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> 33554432</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">130016.2</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 14.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">[./bandwidthTest] test results...</span></span></div><div style="font: 12.0px Helvetica; margin: 0.0px 0.0px 0.0px 0.0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">PASSED</span></span></div><div><br />
</div></blockquote><span class="Apple-style-span" style="font-size: large;"><b>Win7 </b></span><br />
La instalación demoró muchísimo menos tiempo (menos de dos horas totales) comparada con la instalación en Linux (unas 12 horas de lucha).<br />
El deviceQuery entrega CASI los mismos resultados. Hay diferencia en<br />
<br />
<br />
<blockquote><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> Run time limit on kernels: Yes<br />
Device supports Unified Addressing (UVA): No</span></blockquote><br />
<br />
<blockquote></blockquote>que luego investigaremos.<br />
<br />
Por otro lado, el bandwidthTest entrega:<br />
<br />
<blockquote><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> Host to Device Bandwidth, 1 Device(s), Paged memory<br />
Transfer Size (Bytes) Bandwidth(MB/s)<br />
33554432 2521.2<br />
Device to Host Bandwidth, 1 Device(s), Paged memory<br />
Transfer Size (Bytes) Bandwidth(MB/s)<br />
33554432 2551.9<br />
Device to Device Bandwidth, 1 Device(s)<br />
Transfer Size (Bytes) Bandwidth(MB/s)<br />
33554432 130377.2</span></blockquote><br />
<div>que claramente ofrece menos performance que en la versión Linux.</div><div><br />
</div><div><br />
</div>Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.comtag:blogger.com,1999:blog-902407487011295777.post-48618971523629762052011-03-02T21:48:00.000-08:002011-06-01T20:57:14.240-07:00Comparador de performance online para CPU, GPU, etc.No sé si es un hallazgo, pero no dejó de impresionarme tener tanta información para poder decidir sobre uno u otro producto:<br />
<br />
<a href="http://www.anandtech.com/">http://www.anandtech.com</a>Pablo D. Rocahttp://www.blogger.com/profile/16710762210217633077noreply@blogger.com