miércoles, junio 23, 2010
windows apple linux escritorio cuotas
martes, junio 22, 2010
logo vlc
If you use VLC, you might have wondered what the hell is the cone for?
One day, people from the VIA association (VIA is a students’ network association with many clubs … amongst those is VideoLAN.) came back drunk with a cone. They then began a cone collection (which is now quite impressive I must say). Some time later, the VideoLAN project began and they decided to use the cone as their logo.
Lo curioso es que ahora somos muchos los que asociamos el cono de tráfico naranja y blanco a un fantástico reproductor de vídeo.
original
dell rectifica, seguridad linux vs windows
Hace unos días varios medios publicaban una noticia que se originó a partir del sitio web oficial de Dell y de Ubuntu, una distribución que lleva tiempo preinstalando en algunos ordenadores (cada vez más difíciles de encontrar, por cierto), y que según dicha página era una distribución Linux más segura de lo que era el sistema operativo Microsoft Windows.
Parece que la pequeña polémica que generó esa noticia llegó a oídos de los responsables de Dell, que ahora han dado marcha atrás en esa afirmación y la han cambiado con una frase que tan solo dice que “Ubuntu es seguro“, algo que además ha venido acompañado de un párrafo explicativo también menos “agresivo” con respecto a Windows.
Antes se leía: “La inmensa mayoría de virus y spyware desarrollados por hackers no están diseñados para atacar y tener como objetivo a Linux“.
Ahora se lee: “Según informes de la industria, Ubuntu no se ve afectado por la mayor parte de los virus y spyware“.
Parece evidente que Dell ha cambiado dichas frases por la presión de Microsoft, a quien seguramente no le haya gustado nada que el principal fabricante de PCs del mundo afirme algo que le perjudica claramente, sobre todo cuando la inmensa mayoría de los ordenadores que Dell vende en todo el mundo llegan con alguna versión de Windows 7.
En ComputerWorld Steven J. Vaughan-Nichols vuelve a hacer apología de esta noticia indicando que solo han “suavizado” el mensaje, lo que indica que Dell sigue comprometida a utilizar Linux, y que “esto es otra señal de que estamos viendo el principio del fin para la dominación de la informática por parte de Microsoft“.
Me temo que sus impresiones son algo exageradas, pero Nichols siempre ve las cosas de forma muy optimista en el caso de Linux, así que aunque nos alegramos de esa visión, también hay que poner los puntos sobre las íes ;)
lunes, junio 21, 2010
máquinas ajedrez y II
niveles altos pueden ganarlas
En partidas rápidas, las máquinas son superiores.
La razón... es fácil para un humano cometer errores cuando juega un
movimiento en un segundo.
La máquina no juega bien en esas circunstancias, pero no comete errores
En partidas no rápidas, a pesar de que las máquinas calculan millones
de posiciones por segundo, siguen siendo muy inferiores
y eso me sorprende
El ajedrez parece un juego diseñador para una máquina, donde la fuerza
bruta es lo que cuenta... calcular, calcular, calcular...
Y eso es lo que me encanta. Un mísero gran maestro, sólo puede
anticipar un puñadido de movimientos. Sólo puede "calcular" (o
considerar) en cada movimiento, unas decenas de posiciones
diferentes...
Y aún así, su forma de "calcular" machaca a las máquinas.
La máquina calcula como le han enseñado jugadores de ajedrez.
Podríamos pensar que teniendo como profesores jugadores de ajedrez de
primer nivel como maestros y una capacidad de valorar millones de
posiciones según le han enseñado... deberían arrasar
¿dónde está el problema? (para mi más que un problema es romanticismo)
¿Los profesores son buenos jugadores pero malos maestros?
NOOOpp,
Cuando enseñan a humanos, su resultado es muy bueno como maestros
¿No quieren enseñar a las máquinas?
Noooop,
Con la cantidad de dinero que les han untado, en el hipotético caso de
que fuera así, siempre habría sitio para muchos desertores
¿Entonces?
La única respuesta posible es que...
las personas no juegan al ajedrez aplicando algoritmos matemáticos
(bueno, sí, pero no es la parte más importante)
Los humanos aplican una cosa rara llamada intuición y hacen cálculos
muy poco precisos (matemáticamente hablando) para tomar decisiones. Y
con entrenamiento lo hacen muy bien
Eso, para un ordenador con el que pudiéramos hablar, sería magia
Una máquina valorando una posición...
Analizadas 20 millones de posiciones a partir de esta, teniendo en
cuenta que el valor de las piezas es tal y tal, que el valor de las
columnas abiertas es 87, que el valor del peón pasado es 54, pero si
está en una columna es 34 y...
La conclusión es que las blancas están mejor con una puntuación favorable de 46
Un humano viendo la misma posición podría decir...
Sí, hay una pequeña ventaja material y un peón pasado de las blancas,
pero el alfil negro tendrá una participación muy activa en el flanco
del rey. El rey negro llegará al centro de la batalla cuando se
simplifique la presión, más rápido que el blanco que tendrá
dificultades para acceder, etc...
En ningún caso un humano utiliza números ni valores precisos. Un
humano no calculará cómo llegarán los reyes al centro de la batalla,
simplemente dirá... este tardará más.
Y vale, las máquinas juegan muy bien al ajedrez, aunque a pesar de
IBM, están todavía lejos de ser competitivas con grandes maestros
Pero...
Hay un juego muy, muy viejo llamado Go
Ese juego tiene unas reglas muy, muy sencillas. Se aprenden las reglas
en 10 minutos
Los intentos de hacer máquinas de buen nivel jugando al GO han sido
fracasos absolutos.
Las máquinas, al GO juegan terriblemente mal
Y es más
Hay un pirao, que pensó...
voy a diseñar un juego semejante al ajedrez que sea muy complejo para
una máquina
Y se inventó un juego en el que se utilizan las mismas piezas que en
el ajedrez y el mismo tablero
Pero las máquinas lo tendrían muy complicado para jugar bien. No
obstante yo me quedo con el milenario GO
No nos olvidemos de una cosa.
Por mucho que IBM se empeñe en hacerse famosa diciendo lo contrario,
las máquinas son muy, muy tontas desde el punto de vista humano y
animal.
Las máquinas son muy inteligentes triturando números. Sí. Pero para el
resto de cosas...
Un perro reconoce a su dueño muy fácilmente. Además puede detectar su
estado anímico y entender instrucciones habladas, silbadas o de otras
formas
Todavía le queda bastante a las máquinas para entender cosas como...
¿Qué tal hace?
Bueno, no hace mucho calor
En matemáticas hay una rama llamada lógica difusa. Fue la esperanza y
el intento de modelar cosas como la anterior. Nuestro lenguaje es
lógico, pero sólo hasta cierto punto. Está lleno de cosas como la
anterior (y son necesarias)
ibm marketing ajedrez y máquinas
http://alt1040.com/2010/06/
Hace unos años, compitió con Kasparov ¿y le gano?
Según ellos y su marketing sí, y no sólo eso, sino que eso les sirvió
para afirmar que crearon la primera máquina que jugaba mejor al
ajedrez que los humanos
pero la realidad...
Compitieron dos veces.
La primera arrasó Kasparov dejando en evidencia el lamentable nivel
del maquinorro de IBM
En la segunda, empezó igual que la anterior, Kasparov arrasando y sin
ver complicaciones, hasta que pasó algo raro
¿Qué pasó?
Kasparov vio algo raro en un movimiento de la máquina.
Según su opinión, no era un movimiento creíble para la máquina sino
que parecía un movimiento humano
Dicen que le entró una paranoia con dicho movimiento y perdió la
concentración con esa obsesión
Aunque eso tampoco está muy claro
Lo cierto, según los entendidos al ajedrez, es que Kasparov jugó un
par de partidas demasiado malas. Dicen que Kasparov, ni con 6 años
habría jugado tan mal
¿Se desconcentró? Algunos opinan que ni así, que en realidad hubo "chanchullo"
Otra cosa extraña que ocurrió, es que Kasparov exigió que le
demostraran que la máquina hizo ese movimiento y la respuesta fue
sencillamente patética (ya sabes, los ordenadores trabajan con ceros y
unos y eso no lo entiende la gente). En realidad, demostrarlo no
habría sido complicado, pero... no lo hicieron
También hubo críticas en la organización del torneo.
El maquinorro de IBM no sólo tenía todas las partidas de la historia
de Kasparov, sino que durante el torneo, especialistas en ajedrez,
seguían alimentándola, INCLUSO DURANTE LAS PARTIDAS O_o (cosa
claramente irregular y que habría permitido a uno de esos maestros de
ajedrez que estaban detrás, darle un empujoncito en un momento
decisivo)
Dejando de lado lo no demostrable, los especialistas en ajedrez dicen...
* Kasparov jugó increíblemente mal algunas partidas
* La máquina no jugó a un nivel de primera línea humana, jugó muy por debajo
* La organización no fue limpia, no se puede permitir que intervengan
en la máquina durante el torneo (y menos mientras juega)
* La máquina perdió contra otros programas de ajedrez ejecutándose en
arquitecturas mucho menos potentes
* La máquina habría sido arrasada por jugadores buenos (aunque no de
primera línea) especializados en triturar programas
* La máquina, una vez conseguida la publicidad, fue desmontada y
desapareció para siempre
* El programa siguió jugando con resultados mediocres contra personas
e incluso con otros programas
Conclusión...
El que IBM creó una máquina capaz de llegar y superar el nivel de un
jugador de ajedrez de primer nivel, es falso. Tan solo fue una
costosísima operación de marketing
Y no olvidemos, que el reto de verdad, está en hacer un programa o
máquina que juegue decente al GO, y para eso parece que estamos muy,
muy lejos
lunes, junio 14, 2010
crash en c++ de un programador experimentado
miércoles, junio 09, 2010
robot lunar viejo y vivo
Lunokhod 1, el robot lunar que se niega a morir
Menuda sorpresa se han llevado los chicos de la NASA al descubrir que el Lunokhod 1, uno de los abuelos de la carrera espacial entre EE.UU y la Unión Soviética, siguevivito y coleando. El robot soviético lleva abandonado los últimos 40 años en las llanuras lunares. A pesar de su edad, elLunkhod 1 no sólo se niega a morir, sino que también sigue devolviendo señales láser a la Tierra. “Nos está hablando en voz alta y con claridad”, señala el líder de la investigación,Tom Murphy, de la Universidad de California en San Diego.
De acuerdo con el reporte de la NASA, el 22 de abril, el equipo de Murphy halló alLunokhod 1 y 2. Para mostrar si aún estaban en funcionamiento, lanzó pulsos de láser desde un telescopio de 3.5 metros, ubicado en el Punto Observatorio Apache (mejor conocido como APOLLO) en Nuevo México. Sorprendentemente, el Lunokhod 1 respondió con fuerza. “La mejor señal que hemos recibido del Lunokhod 2 en muchos años de esfuerzo son 750 fotones de regreso, pero tuvimos 2.000 fotones desde el Lunokhod 1 en nuestro primer intento”, apuntó Murphy.
El programa Lunokhod (o Lunojod, por su castellanización) consistió en el envío de dos robots soviéticos que alunizaron en 1970 (L1) y 1973 (L2). Su objetivo era explorar la superficie del sátelite y enviar imágenes. Hasta el momento, estos exploradores han sido los únicos móviles automáticos que han explorado la Luna con una guía a control remoto. 40 años después de su aterrizaje, este reflector es aún lo suficientemente fuerte como para permitir obtener mediciones durante el día lunar. No cabe duda: ¡en antaño sí sabían construir cosas duraderas!
want speed pass by value
Want Speed? Pass by Value.
Be honest: how does the following code make you feel?
std::vector<std::string> get_names(); … std::vector<std::string> const names = get_names();
Frankly, even though I should know better, it makes me nervous. In principle, when get_names()
returns, we have to copy a vector
of string
s. Then, we need to copy it again when we initializenames
, and we need to destroy the first copy. If there are N strings in the vector, each copy could require as many as N+1 memory allocations and a whole slew of cache-unfriendly data accesses as the string contents are copied.
Rather than confront that sort of anxiety, I’ve often fallen back on pass-by-reference to avoid needless copies:
get_names(std::vector<std::string>& out_param ); … std::vector<std::string> names; get_names( names );
Unfortunately, this approach is far from ideal.
- The code grew by 150%
- We’ve had to drop
const
-ness because we’re mutatingnames
. - As functional programmers like to remind us, mutation makes code more complex to reason about by undermining referential transparency and equational reasoning.
- We no longer have strict value semantics1 for
names
.
But is it really necessary to mess up our code in this way to gain efficiency? Fortunately, the answer turns out to be no (and especially not if you are using C++0x). This article is the first in a series that explores rvalues and their impliciations for efficient value semantics in C++.
RValues
Rvalues are expressions that create anonymous temporary objects. The name rvalue refers to the fact that an rvalue expression of builtin type can only appear on the right-hand side of an assignment. Unlike lvalues, which can always be used on the left-hand-side of an assignment, rvalue expressions yield objects without any persistent identity to assign into.2
The important thing about anonymous temporaries for our purposes, though, is that they can only be used once in an expression. How could you possibly refer to such an object a second time? It doesn’t have a name (thus, “anonymous”); and after the full expression is evaluated, the object is destroyed (thus, “temporary”)!
Once you know you are copying from an rvalue, then, it should be possible to “steal” the expensive-to-copy resources from the source object and use them in the target object without anyone noticing. In this case that would mean transferring ownership of the source vector’s dynamically-allocated array of strings to the target vector. If we could somehow get the compiler to execute that “move” operation for us, it would be cheap–almost free–to initialize names
from a vector returned by-value.
That would take care of the second expensive copy, but what about the first? When get_names
returns, in principle, it has to copy the function’s return value from the inside of the function to the outside. Well, it turns out that return values have the same property as anonymous temporaries: they are about to be destroyed, and won’t be used again. So, we could eliminate the first expensive copy in the same way, transferring the resources from the return value on the inside of the function to the anonymous temporary seen by the caller.
Copy Elision and the RVO
The reason I kept writing above that copies were made “in principle” is that the compiler is actually allowed to perform some optimizations based on the same principles we’ve just discussed. This class of optimizations is known formally as copy elision. For example, in theReturn Value Optimization (RVO), the calling function allocates space for the return value on its stack, and passes the address of that memory to the callee. The callee can then construct a return value directly into that space, which eliminates the need to copy from inside to outside. The copy is simply elided, or “edited out,” by the compiler. So in code like the following, no copies are required:
std::vector<std::string> names = get_names();
Also, although the compiler is normally required to make a copy when a function parameter ispassed by value (so modifications to the parameter inside the function can’t affect the caller), it is allowed to elide the copy, and simply use the source object itself, when the source is an rvalue.
1 2 3 4 5 6 7 8 9 10 11 12 | std::vector<std::string> sorted(std::vector<std::string> names) { std::sort(names); return names; } // names is an lvalue; a copy is required so we don't modify names std::vector<std::string> sorted_names1 = sorted( names ); // get_names() is an rvalue expression; we can omit the copy! std::vector<std::string> sorted_names2 = sorted( get_names() ); |
This is pretty remarkable. In principle, in line 12 above, the compiler can eliminate all the worrisome copies, making sorted_names2
the same object as the one created in get_names()
. In practice, though, the principle won’t take us quite that far, as I’ll explain later.
Implications
Although copy elision is never required by the standard, recent versions of every compiler I’ve tested do perform these optimizations today. But even if you don’t feel comfortable returning heavyweight objects by value, copy elision should still change the way you write code.
Consider this cousin of our original sorted(…)
function, which takes names
by const
reference and makes an explicit copy:
std::vector<std::string> sorted2(std::vector<std::string> const& names) // names passed by reference { std::vector<std::string> r(names); // and explicitly copied std::sort(r); return r; }
Although sorted
and sorted2
seem at first to be identical, there could be a huge performance difference if a compiler does copy elision. Even if the actual argument to sorted2
is an rvalue, the source of the copy, names
, is an lvalue,3 so the copy can’t be optimized away. In a sense, copy elision is a victim of the separate compilation model: inside the body of sorted2
, there’s no information about whether the actual argument to the function is an rvalue; outside, at the call site, there’s no indication that a copy of the argument will eventually be made.
That realization leads us directly to this guideline:
Guideline: Don’t copy your function arguments. Instead, pass them by value and let the compiler do the copying.
At worst, if your compiler doesn’t elide copies, performance will be no worse. At best, you’ll see an enormous performance boost.
One place you can apply this guideline immediately is in assignment operators. The canonical, easy-to-write, always-correct, strong-guarantee, copy-and-swap assignment operator is often seen written this way:
T& T::operator=(T const& x) // x is a reference to the source { T tmp(x); // copy construction of tmp does the hard work swap(*this, tmp); // trade our resources for tmp's return *this; // our (old) resources get destroyed with tmp }
but in light of copy elision, that formulation is glaringly inefficient! It’s now “obvious” that the correct way to write a copy-and-swap assignment is:
T& operator=(T x) // x is a copy of the source; hard work already done { swap(*this, x); // trade our resources for x's return *this; // our (old) resources get destroyed with x }
Reality Bites
Of course, lunch is never really free, so I have a couple of caveats.
First, when you pass parameters by reference and copy in the function body, the copy constructor is called from one central location. However, when you pass parameters by value, the compiler generates calls to the copy constructor at the site of each call where lvalue arguments are passed. If the function will be called from many places and code size or locality are serious considerations for your application, it could have a real effect.
On the other hand, it’s easy to build a wrapper function that localizes the copy:
std::vector<std::string> sorted3(std::vector<std::string> const& names) { // copy is generated once, at the site of this call return sorted(names); }
Since the converse doesn’t hold—you can’t get back a lost opportunity for copy elision by wrapping—I recommend you start by following the guideline, and make changes only as you find them to be necessary.
Second, I’ve yet to find a compiler that will elide the copy when a function parameter is returned, as in our implementation of sorted
. When you think about how these elisions are done, it makes sense: without some form of inter-procedural optimization, the caller of sorted
can’t know that the argument (and not some other object) will eventually be returned, so the compiler must allocate separate space on the stack for the argument and the return value.
If you need to return a function parameter, you can still get near-optimal performance by swapping into a default-constructed return value (provided default construction and swap are cheap, as they should be):
std::vector<std::string> sorted(std::vector<std::string> names) { std::sort(names); std::vector<std::string> ret; swap(ret, names); return ret; }
More To Come
Hopefully you now have the ammunition you need to stave off anxiety about passing and returning nontrivial objects by value. But we’re not done yet: now that we’ve covered rvalues, copy elision, and the RVO, we have all the background we need to attack move semantics, rvalue references, perfect forwarding, and more as we continue this article series. See you soon!
Follow this link to the next installment.
Acknowledgements
Howard Hinnant is responsible for key insights that make this article series possible. Andrei Alexandrescu was posting on comp.lang.c++.moderated about how to leverage copy elision years before I took it seriously. Most of all, though, thanks in general to all readers and reviewers!
Googling for a good definition of value semantics turned up nothing for me. Unless someone else can point to one (and maybe even if they can), we’ll be running an article on that topic—in which I promise you a definition—soon. ↩
For a detailed treatment of rvalues and lvalues, please see this excellent article by Dan Saks ↩
Except for
enum
s, every value with a name is an lvalue. ↩