Hommage à Octave

J'ai récemment ré-essayé Octave, suite a un coup de yenamarre de Matlab : leur politique tarifaire est ridicule , quand on veut mettre à jour un matlab 2017 vers matlab 2023 , ils font payer 1000 euros par année de différence au lieu d'une somme fixe forfaitaire. Matlab passe son temps à buguer après chaque update de macOS donc c'est très difficile de continuer à travailler sur une vieille version quand on est macqueux. Avec Sonoma ça a été un vrai festival. Donc ras-le-bol de matlab, ras-le-bol des commerciaux Mathworks qui refusent de faire la moindre ristourne pour les bons clients, et ras-le-bol de la lourdeur de matlab (y'a besoin d'une jvm et c'est d'ailleurs pour cette raison qu'il passe son temps à merdouiller/cesser de fonctionner sur macOS).

Du coup Octave, ben ça marche pas mal du tout en 2023. La rapidité est tout à fait honorable sur un mac récent, et l'IDE qui reprend grosso modo celui de matlab est en Qt et est tout à fait fonctionnel : éditeur, debuggeur, inspecteur de variables, plots, etc. Donc thumb up pour octave et fuck you pour matlab.

Not happy

Did you know that signing Windows binaries has gotten a lot more fun since june 2023 ? It was already a great experience, but not on the same scale as today.

So, up to june 2023, in order to sign windows binaries, you had to choose between buying:

  • an OV certificate, cheaper and easier validation. You pay, you get a phone call for identify verification, and at the end of the process you receive a pkcs12 certificate file. You can copy this file on any computer, it is pretty easy to integrate it in you build servers etc. Life is relatively easy as long as the correct phone number is listed in the phone registry that matters to the company issuing the certificates (in my case it was not..).

Drawback of the OV certificate: Microsoft does not trust you by default, so the first people that will download your signed executables will received a pretty scary warning from Windows Defender SmartScreen, telling them that they most likely have downloaded malware and they should erase it ASAP. Thank you MS, I'm glad I paid $700 for such a great service. After a few days/downloads, the warning is gone as MS now thinks your identity is trustworthy. Until.. 3 years later, when you renew the certificate, and all your earned "trust" is gone.

  • an EV certificate, a bit more expensive, with deeper verification (no sure what), and instead of a pkcs12 file, you get a shiny USB key that must be plugged in the computer doing the signing. You are immediately trusted by Microsoft, none of your users will be scared by the SmartScreen malware alert, but having to deal with a physical token instead of a simple file is such a headache that I have always preferred the OV certificate.

So, on 27 may 2023, I decided to renew our previous OV certificate which was about to expire. The provider I use is Sectigo. I could have been one of the last people on earth to receive a 3-years valid PKCS12 OV Certificate file, but no, what I got was a massive delay, and then a stupid SafeNet USB key that must be plugged when signing a file.

Why did this change ? Apparently there are these guys, named the 'CA/Browser forum', who have decided that handing a pkcs12 file to the user was not secure enough and that it was much more fun to make their life miserable by mailing them a stupid USB dongle.

How miserable ? Well quite a lot, indeed. You get a small USB key, and some software (from Thalès, mind you), the "SafeNet Authentification Client", that must be running when signing files. When you launch it, you get a screen with buttons such as "Change Token Password", "Unlock Tocken" etc. But, you cannot unlock the token because you do not have its password, the company that sold you the USB dongle is not giving you the token password. You can have a look at what is inside the token, and find that there is indeed a certificate at your name. You can only export its public key, not the private part. When signing, the SafeNet software will prompt you for a password. That is not the token admin password, but a "PIN" specific to the certificate. This one you can change.

So, by default, EACH time you sign a file, you get that dialog box from the SafeNet Authentification Client that asks you for the PIN of the certificate. EACH time. But that's not all, if you enter the wrong PIN 3 times, then you just bricked your dongle. This happens really quick... you type too fast once, the second time fails and then you realize your keyboard has switched to qwerty, and now you're already at your last chance then you start to sweat for the last chance) (according to what Sectigo told me, they can un-brick the dongle, so it is not completely bricked, but it is still a massive loss of time).

There is a setting in SafeNet to control the number of tries, but it cannot be changed by me, the 'master' password of the dongle is required, I think. Fortunately it is possible to change a setting so that it asks for the password only once per session instead of every time (until logged out, or until the screen is locked) (url)

Still, even with this setting, you have to enter the password once each time the computer reboots, and windows computer do reboot quite often..

There is no official way to enter the token password from command-line. It has to be typed, from you physical keyboard with your little fingers into that stupid dialog box from SafeNet. So it is not possible to automate builds. Fortunately, people have figured some hacks around this, they are ugly and a bit dangerous since the dongle is locked after three unsuccessful attempts:

  • having an application watching the list of windows displayed, if one window title is "Token Logon", it sends it the password (url)
  • using an undocumented feature of signtool (url) . It works great, but for how long ? What happens when the CA/Browser people find out that people can work around their stupid requirements ?

I saw, after buying that SafeNet USB key, that some providers (not Sectigo) do offer "cloud signing" solutions. Of course it is more expensive, these poor guys have to run servers etc.. I guess in the end, for them, these new requirement from the CA/Browser forum are very good for the business, they will sell both usb keys and cloud signing solutions. For everybody else it is just a TOTAL waste of time. Also, in the end, security will be downgraded instead of improved because everybody will have a script that enters the password automatically when the dialog box appears, and will run it on a Windows boxes with auto-login enabled, because it does not work if the user is not logged on. And then this box will connect to the internet with some half-finished python script so that other machines can connect to it to sign binaries.

A final remark : isn't that strange that I can sign my macOS/iOS binaries from any of my macs, without any stupid Thalès USB dongle plugged in my mac ? If that is safe enough for Apple, why does Microsoft enforce this dongle on us, for a more expensive price, and with a much worse service (the SmartScreen malware warning that appears while the 'reputation' is being built is not what I call a great service) ?

In conclusion: fuck the CA/Browser forum, we were fine with the pkcs12 files.

Integrated GPU and memory throughput

I have recently spent a lot of time trying to understand why the computations of my (audio) app on Windows were slowing down when I moved windows on my screen , or when I switched between workspaces. I though the CPU might just get hot and throttle, but it did not. I thought the audio thread was preempted by another thread, but it did not. I though it was interrupted by a bad graphics card driver (or wifi driver, which is very often the culprit for causing glitches in real-time audio applications), but LatencyMon told me everything was fine.

And it turns out it is just the integrated GPU of my core i7 7700 which is hogging the RAM (the integrated GPU does not have its own RAM, it is shared with the CPU). Since this is on a shitty Lenovo desktop with a single RAM stick, it does not have much bandwidth to share. What makes it even worse is that I have a 4k screen plugged into the integrated GPU, so the GPU has to move a lot of pixels.

A good way to check that is to open a simple webgl demo in the browser, preferably one that does not use much CPU, but uses a lot the GPU (the Windows task manager shows graphics for both). And then run the sisoft sandra memory benchmark with this window visible, and then with the window minimized. In the latter case, I get 11GB/s of memory bandwidth, with a latency of 24ns. But when the opengl window is visible, the bandwidth drops to "5.9G/s" and latency drops to 219ns !!

The bandwidth is divided by 2 and the latency is multiplied by 10 when the GPU is in use. That's really bad, especially if you are running a real-time audio application that needs a stable performance. Ensuring that the CPU is not throttling , and that no other application is consuming too much CPU is not enough, one has also to make sure that the integrated GPU is not killing the performance of the RAM.

I have just ordered two new sticks of RAM (in order to double the bandwidth), and a pci-express graphics card, so hopefully with these two I should be able to get stable performance even when I switch between virtual desktops...

Update: I was right, everything is solved with dual channel memory and an pci-express video card.. The spikes in the cpu load when moving windows or switching workspaces have completely disappeared.

Apple notarization : it sucks

I've been trying to notarize my Fart3000.app the whole afternoon... I was following these directions: hardened-runtime-and-app-notarization . Everything seemed to work ,

xcrun altool --notarization-info blahblah

was displaying

Status: success
Status Message: Package Approved

At first I was happy , until I tried to staple it:

xcrun stapler staple -v Fart3000.app
CloudKit query for Fart3000.app (2/1cff807b7db46318f4c15d93199fc6b3bf454edb) failed due to "record not found".
Could not find base64 encoded ticket in response for 2/1cff807b7db46318f4c15d93199fc6b3bf454edb
The staple and validate action failed! Error 65.

Strange isn't it ? The app is a fat binary with i386 and x86_64 arch. It turned out that if I build only the 64-bit file, then the stapling succeeds...

I don't reality need to built 32-bit versions of the App, so not a big sacrifice, but still it does not smell good, one tools says package approved and the other fails with a stupid and wrong message.

As a bonus, "altool" is a java application so it takes ages to start...

When optimizations cross the border of sanity

I'm a bit annoyed because I have this toy program on my mac:

#include <iostream>
#include <cmath>

int main(int argc, char **) {
  float f = 1, c = 0.1f;
  for (int i=0; i < 45; ++i) {
    std::cerr << "f=" << f << " sqrt(f)=" << sqrt(f) << "\n";
    f *= c;
  }
  return 0;
}

It's pretty simple, and one would expect it to print numbers smaller and smaller until it prints zeroes. That's not what happens when built with clang and the fast-math option on macOS:

clang++ -O1 -ffast-math t.cc && ./a.out
f=1 sqrt(f)=1
f=0.1 sqrt(f)=0.316228
f=0.01 sqrt(f)=0.1
f=0.001 sqrt(f)=0.0316228
f=0.0001 sqrt(f)=0.01
 (skipping some output..)
f=1e-34 sqrt(f)=1e-17
f=1e-35 sqrt(f)=3.16228e-18
f=1e-36 sqrt(f)=1e-18
f=1e-37 sqrt(f)=3.16228e-19
f=1e-38 sqrt(f)=-inf  # WTF ???
f=1e-39 sqrt(f)=-inf
...

So when f is so small that it is represented as a denormal number, the sqrtf function returns PURE GARBAGE instead of returning 0. Or any denormal number. I would accept anything, but not, for fucks sake, a negative number. Not -inf. Please.

I have reported this to Apple (more than one year ago) , I got a reply (one year later), and for them it is not an issue, because the argument of sqrtf being smaller than FLT_MIN allows undefined behaviour (!??). Well, let's agree to disagree. I don't think fast-math should allow the compiler to do whatever it wants. Denormal numbers do happen. Sqrtf is a common function. There is a difference between being fast and slightly incorrect, and being fast and absolutely wrong.

Note: I have not been able to reproduce it with gcc or msvc, or even clang on linux. It is only the mac version of clang/libc++ which is retarded.

Ajouter le support du séquenceur midi ALSA quand il n'est pas fourni d'emblée avec le noyau

Assez souvent avec les noyaux linux qui sont fournis avec les cartes ARM ont un minimum de modules d'activé, et bien souvent le séquenceur ALSA n'en fait pas partie. Comme ça fait plusieurs fois que je fais la manip et que j'oublie à chaque fois les differentes étapes voici ce que j'ai fait pour avoir le séquenceur alsa sur une carte NanoPi Neo 2 sans s'emmerder à recompiler un kernel entier. Recuperer les sources correspondant au kernel courant, dans mon cas sur le github de friendlyarm . Le dossier linux n'a pas de .config, y'en a pas dans /proc/config.gz , pour en recuperer un aller dans fa_tools et faire un ./build.sh -b nanopi-neo2 -p linux -t kernel . Ca échoue rapidement mais on s'en fout maintenant y'a un .config dans le dossier linux.

Donc:

cd linux
make menuconfig
et aller dans drivers / soundcard pour rajouter le support du sequenceur alsa sous forme de module.

Il faut aussi recuperer Modules.symvers:

cp /lib/modules/3.10.65/Module.symvers .

Faire

make prepare && make scripts
make CC=gcc-4.9 M=sound/core/seq/
sudo make CC=gcc-4.9 M=sound/core/seq/ modules_install
depmod -a

et voilà normalement on peut maintenant faire un modprobe snd-seq et ça roule.

Executer un binaire arm 32-bit sur une distrib 64-bit (aarch64)

En fait c'est comme pour le i386 / amd64 , sur une distrib debian-like il faut commencer par un dpkg --add-architecture armhf (ou armel selon ce qu'on veut) , un apt-get update, un apt-get install libc6:armhf et ça roule.

Le macbook pro 2016 avec sa touchbar magique et révolutionnaire

pas content J'ai un macbook pro 2016 depuis un bon gros mois et ça y est j'en ai marre faut que ça sorte. Ce matin il a refusé de sortir de veille, et ce soir cette bourrique qui renacle a obstinément refusé de se mettre veille. D'ailleurs la sortie de veille est un problème récurrent sur ce mac, il semblerait que l'adapteur pour écran externe hdmi soit dans le coup. Des fois en sortant de veille , ou en s'éteignant, je vois apparaitre des rectangles rouges sur l'écran du mac, en général c'est quand il renacle. C'est le genre de truc sur un vieux laptop dell sous windows on se dit "pff les drivers MACHIN c'est vraiment de la merde" ou "purée windows c'est vraiment de la merde en branche", mais là comme c'est un laptop apple "que c'est les meilleurs parce qu'ils controlent le matos et le soft et c'est pour ça que l'experience utilisateur est tellement léchée et polie" ben ça pique un peu. On pourrait aussi parler de l'adapteur pour écran externe, vendu par apple, pour la modique somme de 59euros et qui semble être impliqué dans pas mal de problèmes, cf ses notes et reviews ici: usb-c-digital-av-multiport-adapter

La grosse nouveauté de ce macbook c'est sa touchbar. Elle permet (et c'est sans doute son usage le plus spectaculaire) d'afficher la liste entière des emojis unicode quand on rédige un mail , c'est assez impressionnant et bien sûr crucialement utile. On trouve aussi sur internet plein de gens qui disent que la touche escape transformée en touche non physique sur la touchbar eh ben "saipagrave", personnellement je penche plus pour le "sapuducul". Ca m'a donné l'occasion de réaliser qu'en position de repos j'ai tendance à laisser trainer le petit doigt pas loin de cette touche escape et comme maintenant elle s'active dès qu'elle est frôlée j'ai tendance à balancer des rafales de ESC intempestifs dans emacs ou dans le terminal (des rafales parce que tant qu'on laisse le doigt dessus elle passe en mode autorepeat, c'est vraiment malin). En mode rédaction de mail, un bouton 'Send' apparait juste à côté de la touche escape, ce qui est une riche idée sauf pour ceux qui ont l'habitude d'avoir le petit doigt qui traine dans le coin. A l'extrême droite y'a le bouton marinesiri que j'ai aussi pas mal tendance à activer par erreur. Le réglage du volume sonore se fait aussi sur la touchbar, mais là ou autrefois on avait une touche pour augmenter, une touche pour baisser, il faut maintenant appuyer d'abord sur un bouton qui fait apparaitre un slider pour ensuite ajuster le volume, c'est très joli mais ça fait deux "clics" au lieu d'un. A part ça, la touchbar ne me sert à rien. Donc en gros on peut un peu dire que la touchbar c'est de la merde. Peut être qu'avec du retour haptique elle serait potable.

Le clavier est nouveau aussi, et il n'est ni magique ni révolutionnaire. En plus il fait du bruit (dans le bureau c'est clairement moi qui ai le clavier le plus bruyant maintenant), et ce n'est pas un bruit soigneusement designé qui évoque le matos cher et sophistiqué, mais plutot un vieux ploc cartonné qui me rappelle les pires netbooks avec leur claviers mous et gondolés. En plus je n'arrête pas de faire des fautes de frappe sur ce clavier.

Le bruit: j'ai pris le modele quad-coeur core i7 pour avoir une machine qui a la niaque quand il s'agit de compiler des trucs. Eh bien au bout de 10 minutes de compilation intensive le macbook réussit à faire plus de bruit que mon ancien mac pro (la grosse tour qui pèse au moins 200kg). Pas mal ! Et ça n'empeche pas le cpu d'être à 100°C (d'après l'application intel dont j'ai oublié le nom). Donc le corps du mac est confortablement chaud, comme une bonne bouillote de mamie, j'ai hâte de voir ce que ça va donner cet été.

Une feature sympa quand même: le touch-id , qui marche bien et j'apprécie de devoir saisir mon mot de passe un peu moins souvent. Et l'usb-C, si on oublie l'adapteur hdmi moisi de apple , pour le reste c'est plutot sympa.

En conclusion je décerne un 2/20 à ce macbook.

De la fragilité des outils de debug

Une des choses les plus exaspérantes avec le dev en c/c++ c'est de ne pas comprendre *pourquoi* tel outil de profiling ou de debugage n'est pas foutu d'afficher les noms de fonctions corrects, ou d'afficher le code source. C'est par exemple perdre des heures à chercher pourquoi la fonction backtrace de la glibc a besoin d'une option particuliere du compilateur (-rpath) pour donner des noms de fonctions au lieu de leur addresse, alors que celle de la libunwind se demerde toute seule comme une grande. C'est perdre des heures à chercher comment faire en sorte que perf sous linux sur arm affiche des noms de symboles plutot que des addresses hexa. Ca n'est pas spécifique à une plateforme, sur *chaque* plateforme je me retrouve à un moment où a un autre à me battre contre des outils récalcitrants et autistes , qui ne fonctionnent pas et qui ne disent pas quel est leur problème. Mentions spéciales à perf sous linux, windbg sous windows et Instruments.app sous macos.

Et donc pour Instruments.app , ce qui est nécessaire si on veut que cette mule soit capable d'annoter les sources du code profilé, c'est de bien veiller à compiler les sources en donnant le chemin *absolu* à clang, et non pas un chemin relatif.

Editer un script bash pendant qu'il est en cours d'execution

On est en 2016 et bash n'est toujours pas capable de gérer correctement la situation où on édite un script alors qu'il est en cours d'exécution (gérer correctement, càd ignorer les changements et continuer à executer le script initial, et pas tenter d'executer un bout semi-aléatoire de la nouvelle version du script pour finalement se planter comme une merde)

Performance of the Raspberry pi 3

I just got a raspberry pi 3. I used to assume that its cpu (Cortex A53) should be quite bad, even when related to a good old cortex A9 (for example this document says that the performance is expected to be equivalent for both, while this one says the A53 is slightly slower than the A9). As I now have a cortex A9 (rk3188t) on a cheap device running picuntu, and a cortex A53 on the raspberry Pi, I can compare them. The default speed of the rk3188t is 1.4GHz but I have lowered it to the frequency of the raspberry pi for an easier comparison (using cpufreq-set). So both cpus are running at 1.2GHz. For the performance comparison, I have built and run the pffft benchmark on both:

time gcc-4.8 -O3 -DHAVE_FFTW -march=armv7-a -mtune=cortex-a9 -mfloat-abi=hard -mfpu=neon -ffast-math test_pffft.c pffft.c -o test_pffft_arm fftpack.c -lm -lfftw3f

(the raspbian distribution of the rpi3 is 32-bit so what I'm comparing here , since the A53 is 64-bit capable, is a A9 with a A53 running in 32-bit)

On the rk3188t@1.2Ghz, the compilation took 34 sec , while it took 24.9 on the pi, which is here 36% faster.

The execution took 109 sec on the rk3188t vs 66 sec on the pi, so for floating point stuff the pi is 65% faster.

If I look at the floatting point performance for pffft itself (so it is a measure of the neon simd floating point, not of the scalar floating point performance), the rk3188 reports a max value of 1164 MFlops for FFTs of length 1024 , while on the raspberry pi it achieves 2162 MFlops . So for neon stuff, the pi is 85% faster !

Here are the pffft results for the pi 3 on raspbian (when built with gcc-4.9 , which itself improves the pffft performance of 20% on both the rk3188 and the pi3 with respect to gcc-4.8, and with -mtune=cortex-a53 instead of cortex-a9, which brings another 7% of improvement):

| input len |real FFTPack|  real FFTW | real PFFFT | |cplx FFTPack|  cplx FFTW | cplx PFFFT |
|       64  |      521   |      672   |     1303   | |      534   |      887   |     1470   |
|       96  |      429   |      340   |     1253   | |      422   |      864   |     1323   |
|      128  |      508   |      740   |     1571   | |      491   |      742   |     1502   |
|      160  |      525   |      750   |     1626   | |      483   |      931   |     1463   |
|      192  |      544   |      852   |     1641   | |      495   |      877   |     1548   |
|      256  |      639   |      684   |     2007   | |      570   |      778   |     1727   |
|      384  |      483   |      873   |     1724   | |      436   |      795   |     1531   |
|      480  |      495   |      761   |     1749   | |      433   |     1040   |     1492   |
|      512  |      548   |      765   |     2043   | |      489   |      873   |     1670   |
|      640  |      557   |      892   |     2004   | |      481   |      863   |     1579   |
|      768  |      571   |      818   |     1980   | |      486   |      892   |     1684   |
|      800  |      549   |      637   |     1928   | |      450   |      657   |     1564   |
|     1024  |      645   |      842   |     2328   | |      540   |      914   |     1764   |
|     2048  |      586   |      869   |     2151   | |      487   |      931   |     1583   |
|     2400  |      530   |      672   |     1803   | |      422   |      681   |     1379   |
|     4096  |      631   |      867   |     2079   | |      476   |      843   |     1439   |
|     8192  |      515   |      811   |     1611   | |      418   |      730   |     1345   |
|     9216  |      503   |      789   |     1568   | |      424   |      812   |     1347   |
|    16384  |      501   |      749   |     1552   | |      418   |      699   |     1239   |
|    32768  |      479   |      680   |     1396   | |      346   |      529   |      825   |
|   262144  |      244   |      327   |      398   | |      240   |      409   |      387   |
|  1048576  |      229   |      270   |      350   | |      211   |      301   |      355   |

update: maybe I should say a word about the audio quality of the built-in headphone output of the rpi3 ? it is utter crap. Not sure if mine has a hardware issue or if the driver is doing some crazy shit but the output is mixed with some horrible electronic noise coming

chrooter une veille debian pour compiler des trucs

Quelques notes pour que je me souvienne comment on met en place une debian wheezy sous ubuntu tranquillos (ici avec une abi armhf):

  • installer schroot:
> apt-get install schroot
  • debootstraper la wheezy:
> debootstrap --arch armhf --foreign wheezy /armhf-wheezy http://ftp.fr.debian.org/debian
  • configurer le schroot:
> sudo vim /etc/schroot/schroot.conf

Et y entrer:

[armhf-wheezy]
description=Debian Wheezy, ARMHF
type=directory
directory=/armhf-wheezy
users=MONLOGINDEUSER
root-groups=root
aliases=armhf,default

Comme ça le home sera directement utilisable dans le chroot.

  • finir le debootstrap:
> sudo schroot
# /debootstrap/debootstrap --second-stage
# cat > /etc/apt/sources.list
deb http://ftp.fr.debian.org/debian wheezy main
deb http://httpredir.debian.org/debian wheezy-updates main
^D
# apt-get update
# apt-get install g++ libasound2-dev scons make vim

Si il y a des montage qui n'apparaissent pas dans le chroot, le plus simple et d'editer /etc/schroot/default/fstab et de les rajouter dedans.

Et c'est bon, on a un environnement de dev un peu vintage qui permet de fabriquer des binaires bien compatibles puisque compilés sur une vieille debian des familles.

Recyclage de clef-pc

C'est pas beau ça ?

Je ne suis pas peu fier d'avoir fabriqué un magnifique mini-pc équipé d'un nombre raisonnable de ports usb et d'une sortie son qui marche à partir de divers éléments inutiles et plus ou moins fonctionnels:

  • une clef-pc meegopad T02 , livrée avec un ubuntu qui ne boote que si on prend le soin de visiter le bios avant de la booter..
  • un vieux hub et divers bouts de cables usb
  • un lcd usb crystalfontz
  • un boite vide de "Mon Chéri" , en plastique rouge translucide, avec cette élégance subtile teintée de bon gout typique des produits Ferrero .
  • une boite de tic-tac
  • un bout de ferraille pour lester le fond du boitier
  • une carte son externe usb d'une valeur de 2 euros

Quand le boitier est ouvert ça donne quelque chose d'élégant et pas du tout bordelique.

Il s'avère que la clef-pc (baytrail z3537f, 2go de ram) accepte de booter toute seul si on lui met une distro 32-bit plutôt que 64-bit donc j'ai remplacé la ubuntu inutile et je lui ai collé une debian Jessie. Il s'avère aussi que le temps s'écoule de façon bizarre sur cette clef pc, il ralenti, il accélère il fait des bonds, et au final y'a des trucs qui marchent pas très bien (par exemple le mécanisme de répétition automatique des touches du clavier n'aime pas qd le temps fait des bonds en arrière). En mettant "clocksource=tsc" sur la ligne de commande du kernel ça marche mieux. Il s'avère enfin que la présence du lcd sur le meme hub usb que la carte son a tendance a produire des craquements dans celle-ci. Je pensais que c'était un probleme électrique (vu que j'ai du raccourcir et bricoler les câbles usb pour que ça loge dans le boitier), mais les craquement ne se produisent (semi-aleatoirement) que quand le device /dev/ttyUSB0 du lcd est open(). Du coup j'ai installé un kernel avec un HZ à 1000 et ça va nettement mieux. Mais je n'ai pas vraiment compris quelle est la nature du problème...

Le cpu est un atom baytrail à 1.33Ghz avec turbo boost à 1.8Ghz. Par défaut le turbo n'est pas activé et il n'y a pas de réglage dans le bios pour l'activer. On pourrait croire que la situation est désespérée, mais non, cette page donne des instruction qui permettent effectivement d'activer le turbo, et ça fait une différence notable en performance. Le wattmètre indique 7W et la température du cpu reste sous contrôle.

A l'arrivée le boitier fait tourner un synth avec une taille de buffer de 64 samples finger in the nose. Le synth est piloté par un petit script python qui s'occupe de l'interaction avec le LCD l'affichage, changer de preset, ou éteindre le boitier.

UPDATE: finalement le LCD provoque encore des craquements avec le kernel liquorix... rogntudju.

Ultra short c++ MIDI file reader

There are many full-featured libraries for reading Standard MIDI Files , but they are often doing more than just reading and end up being a bit on the over-engineered side.

Here is what could be the shortest MIDI file parser ever, in a simple self-contained c++ header file. It is short because it does not do much and does not try to be smart.

simple_midi_reader.hh

It should be able to load any MIDI file and turn it into a list of MIDI events that are correctly timestamped (tempo change events are handled). And that's all !

Wow

Wow ça fait longtemps que j'ai pas blogué.

Prompt bash

Ca faisait au moins 10 ans que j'utilisais le même prompt bash, un truc qui affiche grosso modo l'heure et le chemin courant, en couleur, basique mais leger. Un truc qui me manque parfois c'est d'avoir le temps d'execution de la derniere commande, je trouve que c'est une information interessante quand ce temps est de plus de quelques secondes. Et aussi, avoir un affichage du code de retour de la commande précedente. C'est pourquoi j'ai décidé de mettre a jour mon prompt bash ! voici ce qu'il y a maintenant dans le ~/.bashrc , il n'y a rien d'exceptionnel c'est juste des bouts de trucs trouvés sur le net mais je suis content du résultat:

url du truc (arg je n'arrive pas à coller le code directement dans dotclear, il a l'air d'en interpreter des bouts...)





Voila la tête que ça a:

Je ne vais pas dire que c'est le plus beau prompt du monde, mais je sens qu'il va faire l'affaire pour les 10 ans venir.

Utiliser -mfpmath=sse avec gcc

Un bon moyen (en 32-bit) pour se debarrasser des bizarreries du x87 c'est de compiler avec cette option -mfpmath=sse qui demande à gcc d'utiliser les instructions sse à la place du x87 et ses registres moyenageux de 80-bits. Jusque là tout va sauf que si on regarde les performances des fonctions transcendentales expf, sinf, tan, atan ( par exemple en compilant sse_mathfun_test.c avec les options -ffast-math -O3 -msse2 et -mfpmath=sse ou -mfpmath=387), eh bien on constate qu'elles sont devenues jusqu'à 2.5 fois plus lentes. Genre sur mon core 2, tan() executée avec le fpu x87 prend 119 cycles, alors que la version sse2 prend 298 cycles ! pas cool. Pour expf c'est un peu moins pire, on passe de 143 cycles à 203.

J'ai fait le test avec mingw-w64 sous windows, version 4.6.2 et 4.7.

(Coté visual c++ 2010, le runtime selectionne systematiquement la version sse2 à l'execution, mais elle est beaucoup plus rapide que celle de gcc: 146 cycles pour tan, 103 pour expf)

Latence du nexus 7

Après des mesures scientifiques, la latence "touch to fart" du nexus 7 est de 200ms (au mieux -- pour la premier application testée c'était 400ms)

Update: en fait j'avais testé avec divers synths et grand pianos, mais pas avec un vrai fart piano, et... c'est lui qui a la latence la plus faible, ~120ms ... Il semblerait que ce soit parce qu'il utilise l'api soundpool qui permet de jouer des samples predefinis avec une latence plus faible que les autres api. Mais elle n'est pas utilisable si on doit faire de la synthese ou appliquer des effets sur les samples

Google Nexus 7

Hé ouais j'ai un nexus 7 depuis quelques jours. Vous êtes incroyablement nombreux à réclamer un billet de blog à ce sujet, voici donc un petit compte-rendu:

  • j'aime bien le dos. Je comprends pourquoi chaque article sur le nexus 7 en parle, c'est un truc assez reussi pour du plastoc. C'est vraiment agréable au toucher et ça ne fait pas cheap.
  • l'écran est sympa, sans etre une resolution de folie (1280x800) ça fait quand même des pixels bien petits. Par contre faut une vue pas trop mauvaise.
  • la tablette est livrée avec 'A la recherche du temps perdu' et 'Transformers III' , manifestement google n'a pas peur des contrastes forts. On a du mal à imaginer un film plus con que transformers III.
  • jelly bean est fluide
  • ça ne chauffe pas, enfin je crois. Faudrait quand même voir en faisant tourner les 4 cores à 100% , ça doit bien finir pas devenir au moins tiede.
  • y'a pas de dock digne de ce nom, qui permettrait de brancher un périphérique usb tout en rechargeant la tablette: sainul.
  • le micro-usb c'est quand même un bien pénible a brancher/débrancher , je comprends pourquoi apple n'a pas voulu se faire chier avec ce truc.
  • l'installation du sdk + ndk android est quand même bien pourrie , le nombre de machins a installer (java, ant, eclipse, sdk, ndk, plugin eclipse, telecharger les images et les libs pour diverses releases d'android, préparer des devices virtuels pour les tests)
  • c'est quand même un peu long pour deployer une application sur la machine, genre un paquet de 13Mo prend environ 20secondes pour etre installé sur le nexus 7. Ca reste quand même nettement plus rapide que dans l'emulateur.
  • la latence audio est A PLEURER. Quand je joue du fart piano il y a bien un quart de second qui s'écoule entre le relachement de la la touche et le bruit de pet. ça valait vraiment la peine que google se vante de la latence "améliorée" dans jelly bean. Vraiment ça craint. Et en passant par opensl c'est pas mieux (en fait je crois que c'est pire, j'ai l'impression d'avoir plus d'un quart de seconde de latence)
  • y'a zero api pour gerer les periph MIDI branchés sur le port usb, encore un signe que google n'a vraiment rien a foutre de l'audio. La solution c'est de réinventer la roue avec ce genre de truc: android USB-MIDI driver. On dirait aussi que brancher et debrancher des trucs USB a tendance a faire planter la tablette..
  • le tegra 3 n'est quasiment jamais à 1.3GHz , sa fréquence de croisière quand il y a de la charge semble être 1.2GHz , et sinon il descend très vite en fréquence, 100MHz quand la tablette est idle

Google WEBP roxor

Voila un format d'image qui n'a pas reçu beaucoup d'amour quand il a été annoncé, qui n'est pas supporté par firefox, qui n'est pas encore complètement sec (y'a un gros TODO pour les PPC dans le code), et pourtant il est déjà bien. Carrément meilleur que jpg pour les images qui m'intéressent (des bitmaps assez détaillés avec parfois du texte), il permet de remplacer completement le png puisqu'il supporte la transparence. La décompression est très rapide, la lib est raisonnablement petite et portable, bref c'est de la boulette. J'avais commencé à m'intéresser à sa variante webpll pour faire du lossless, mais c'est nettement plus long a compresser/décompresser, ça ne fait que 30% de mieux que le png et webp me permet d'obtenir la qualité d'image souhaitée avec des images beaucoup plus petites.

Donc merci google pour webp, c'est vraiment sympa.

Gros dictionnaire

Un truc dont j'ai pris conscience très récemment, c'est l'importance de la taille du dictionnaire pour des algos de compression genre lzma, quand on compresse des données relativement redondantes. L'exemple typique, c'est un fichier tar contenant plusieurs fois le même fichier avec juste quelques petites altérations, le genre de chose qui arrive de temps en temps, et en tout cas qui m'arrive à moi. Si le dictionnaire lzma est assez gros, alors la compression va capter toutes ces redondances et va compresser *beaucoup plus* que si on utilise le dictionnaire par défaut. Si il est trop petit, ben ça va marcher beaucoup moins bien.

Du coup , sous linux, en utilisant un dictionnaire de 128MB (la valeur par défaut est 8MB) mon archive .7z de 54Mo passe à 19Mo seulement ! Impressive.

Ca marche aussi pour un setup.exe sous windows. Si on utilise l'excellent innosetup il y a une option pour modifier la taille de dictionnaire lzma, avec la même efficacité. C'est aussi possible avec nsis (que j'exècre), mais il faut aussi lui demander explicitement de faire une compression "solid" c-à-d de comprimer tous les fichiers en même temps, et pas un par un.

Par contre le plus gros défi c'était d'en profiter aussi sous macos. C'est plus compliqué sous osx puisque PackageMaker utilise gzip pour compresser l'archive mpkg, et là y'a pas d'options ( je ralais déjà à ce sujet ici , mais a l'époque je ne connaissais pas la feinte du dictionnaire lzma pour gagner encore plus en compression). Du coup j'ai fait une petite appli cocoa , qui embarque le mpkg dans ses ressources. Mais c'est un mpkg dont le Archive.pax.gz (qui est grosso modo un tar.gz de tous ce qu'il y a à installer) a été d'abord dégzippé puis recompressé avec lzma et un gros dictionnaire bien touffu. L'appli copie ce mpkg dans un dossier temporaire, décompresse le Archive.pax.lzma et passe ensuite le relai à l'installeur d'osx pour installer le mpkg (même pas besoin de le re-gzipper, manifestement l'installeur macos s'en accomode très bien).

Du coup on va économiser un peu de bande passante et je poireauterai un peu moins pendant les uploads de nouvelle version.

pretty fast FFT

Voici le code d'une FFT raisonnablement rapide, raisonnablement petite (le code tient dans un fichier) et raisonnablement pas chiante au niveau de la license (c'est du bsd). Paradoxalement, ce n'était pas facile d'en trouver une qui réponde à ces contraintes.

Que s'appelorio PFFFT.

rogntudju

En l'espace de deux jours, je viens de découvrir que l'imac acheté il y a un an et trois mois (donc plus sous garantie) a des taches qui se développent sur la dalle, et ce matin son disque dur a laché (enfin pas sûr a 100% mais le fait qu'il ait affiché des I/O error et ramé comme un phoque avant de refuser de rebooter et que les fsck echouent piteusement me rend peu optimiste).

J'ai un peu les boules.

Update: finalement il y a eu une happy end et je n'ai plus du tout les boules !

Format AIFF

mega sample rate vs giga float

J'étais en train de regarder le format des fichiers des AIFF (le .wav d'Apple), qui semble a priori un format assez basique, et pourtant mes bras m'en sont tombés quand j'ai vu comment il codent la fréquence d'echantillonnage du fichier: sur un ieee long double , un float géant de 10 bytes ! je me demande ce qui est passé dans la tête du type qui a pondu ça.

Excellent blog

Je kiffe: http://pulsar.webshaker.net/

clock_gettime is slow

..on the pandaboard. I just measured it , and each call to clock_gettime(CLOCK_MONOTONIC) takes approximately 800ns . On a core 2 quad it takes 27ns , and it has also a muuuuchh better resolution that the ARM one, which has a resolution of 1/32787th second. Using CLOCK_REALTIME or whatever does not improve the timings.

NEON optimized single precision sin / cos / exp and log

This is a translation of the SSE version to ARM NEON intrinsics. Je profite de l'occasion pour dire que : the official ARM NEON documentation is quite shitty.

ARM Cortex A9 Peak FLOPS

I have just measured the peak gflops performance for the cortex A9, using this snippet of code:



@@ int ni = 65536*16;

   __asm__ volatile("mov  r5, #0\n"
                    "vdup.f32 q0, r5\n"
                    "vdup.f32 q1, r5\n"
                    "vdup.f32 q2, r5\n"
                    "vdup.f32 q3, r5\n"
                    "vdup.f32 q4, r5\n"
                    "mov r5, %0\n"
                    "1:\n"
                    "vmla.f32 q0, q0, q0\n"
                    "vmla.f32 q1, q1, q1\n"
                    "vmla.f32 q2, q2, q2\n"
                    "vmla.f32 q3, q3, q3\n"
                    "vmla.f32 q4, q4, q4\n"
                    "subs r5, r5, #1\n"
                    "bne 1b\n" : : "r"(ni) : "q0", "q1", "q2", "q3", "q4", "r5");@@

Each loop does (4 float per vec) * (5 vmla operations) * (2 flop per vlma) = 40 flop, repeated ni times. The result for the 1GHz cortex A9 of my pandaboard: 3.99919 GFlops , which was quite expected but it is always good to see a confirmation. Reducing the number of VMLA (fused multiply add) in the loop results in a lower performance (the vlma latency is 5 cycles if I recall correctly, so that is also expected). Using separate VMUL and VADD operations produces 2 GFlops instead of 4.

Interestingly, replacing the five VLMA on size-4 vectors by 10 VLMA on size-2 vector produces almost the peak 4 GFlops: 3.64 GFlops.

Assembleur ARM

Vous serez heureux d'apprendre que je commence à masteuriser l'assembleur ARM ! gcc a quand même un peu de mal à pondre du code optimal pour NEON , et le cortex-A9 n'est quand même pas un foudre de guerre. Donc au lieu de passer mon temps à rearranger le code C un peu au pif pour qu'en sortie gcc recrache de l'asm bien gaulé, je me suis décidé a faire directement de l'asm. Un bon exemple se trouve dans les sources de ffmpeg, il y a même une FFT dont je suis sûr qu'elle dépote les platypus.

Et le fait est que les instructions NEON sont largement mieux foutues que l'espece de truc bancal qu'est SSE, avec ses 8 pauvres registres 128 bits, ses instructions qui ecrasent toujours une des deux operandes, et son shuffle dont chaque utilisation donne l'impression d'être en train de résoudre un problème de rubik-cube. NEON c'est 16 registres 128 bits, qui peuvent etre manipulés comme 32 registres 64-bits, des instructions avec deux registres sources et un registre destination (comme altivec). Des instructions plutot claires et non ambigues (contrairements aux shuffle/unpacklo/unpackhi/movehl,movelh etc de sse). Des instructions load/store pas chiantes avec l'alignement , par defaut elles marchent sur des données non alignées sur 16-bytes, mais si on est sûr de l'alignement on peut leur donner un hint qui permet de gagner quelque chose comme 10% de vitesse. Pas sûr qu'on puisse encore considerer tout ça comme du RISC, par exemple : vld1 {q0,q1}, [r0,:256]! charge d'un coup 32 octets dans les deux registres q0 et q1 , avec un hint d'alignement sur 256-bits, et post-incrémente r0 d'autant. Du coup, sur les calculs qui sont assez soft avec la mémoire j'arrive à approcher les 2 GFlops sur un coeur de cortex A9 à 1GHz ce qui commence a être assez satisfaisant.

Pandaboard

Depuis une semaine j'ai une Pandaboard ! Contrairement au toshiba AC100 avec son tegra2 qui pue, celle-ci est basée sur le OMAP4 de texas instruments, qui a une unité SIMD NEON, comme tous les autres cortex A9 et le futur tegra 3. Le cpu dual core fonctionne a 1GHz, la carte mesure 10x12cm , actuellement elle tourne sous ubuntu 11.04 et consomme 4W (mais je ne suis pas sur du tout de la precision du wattmetre). En gros c'est de la boulette.

Optimization tip for SCons on cygwin

Do not build many Environment() ! build one, and clone it when you need it. Each time Environment() is built, it prepares for the "mingw" tools, and this calls "gcc --version" and "g++ --version". On cygwin, where forking is extremely slow, this can take ages.

Python

python vient d'être élu Best Programming Language par les lecteurs du Linux Journal.

Ahhhh python....

def python_is_ok(s='do not sux'):
        print s
        s='sux'

def python_sux(l={}):
        if 'sux' in l:
                raise Exception('python sux')
        l['sux']=True

python_is_ok() # ok..
python_is_ok() # ok..

python_sux() # OK...
python_sux() # fail..

outputs:

do not sux
do not sux
Traceback (most recent call last):
  File "sux.py", line 13, in <module>
    python_sux() # fail..
  File "sux.py", line 7, in python_sux
    raise Exception('python sux')
Exception: python sux

Ok, ce comportement bizarre est indiqué dans le tutoriel de python, n'empeche que c'est louche.

A not so minimalistic OSC library

Finalement j'ai trouvé une utilité à oscpkt, ce n'est pas l'usage que je prévoyais quand j'ai commencé mais ça ma donné l'occasion de fignoler un peu le truc, de le rendre cross-plateforme (pour la partie sockets) et d'y ajouter le pattern matching sur les chemins OSC. J'ai aussi agrémenté la homepage avec une image de Troy McClure.

Ultra minimalistic OSC library

oscpkt , si ça peut servir à quelqu'un faites vous plaisir.

Quick comparison of the ARM Cortex A9 and Intel Atom

Here are two small benchmarks that I have just run on an Intel Atom N270, running at 1.6GHz, and a ARM Cortex A9 castrated by nvidia (the neon unit has been ablated in tegra2). The arm is a dual-core cpu running at 1GHz. Both are running ubuntu, the compiler used being gcc 4.4.

First bench: compilation of a very large (250000 lines) c++ file. This stresses the cpu and memory, but not the swap (the ARM one does not even have any swap). The compilation consumes ~300MB. This is of course a single-threaded test.

  • Atom: 1m15 sec.
  • Cortex: 1m49 sec.

That is a ratio of 1.44. gcc 4.4 on the Atom is much faster than on the cortex A9 (this is the gcc version of ubuntu maverick, so it is built for ARMv7).

The second test compares the anemic VFP floatting point unit of the Cortex A9 with the old Atom fpu. This is a typical linear system solve, in double precision, with pretty straighforward scalar code without any specific optimization or tricks, repeated 100 times. Standard compiler optimisations ( -O3 -ffast-math , with also -mfpu=vfpv3-d16 -march=cortex-a9 for the ARM)

  • Atom: t=4.68 sec.
  • Cortex: t=6.16 sec.

The ratio is 1.31 , so basically the same as the gcc compilation bench. Clock for clock, the cortex is slightly faster than Atom, but the Atom has a higher clock. And it still has its ballsSIMD unit, which will allow any Atom to humiliate the tegra2 cpu in any single precision floating point benchmark.

ARM d'honneur

Je commence à regarder la documentation de NEON, l'unité simd des ARM Cortex A8 et supérieurs. Il n'y a pas encore des masses de docs "accessibles" à ce sujet, pas évident de trouver des tutoriaux de la qualité de ceux qui existent pour Altivec ou SSE. On trouve quand même une série d'articles très interessants sur blogs.arm.com:

Et franchement après avoir lu ça on ne peut qu'éprouver un sentiment de gêne pour Intel et son SSE tellement rustique qu'il fait figure d'idiot du village (le village des instructions simd). Car oui, NEON n'est pas psychorigide sur les questions d'alignement mémoire (et c'est *tellement* chiant avec SSE, et un peu chiant avec altivec). Il est aussi capable d'opérations de shuffling très avancées, avec la possibilité, en une seule instruction, de charger, désentrelacer jusqu'à 4 vecteurs 64 bits ET de post-incrementer le registre d'adresse d'une valeur abitraire. Take that, SSE. Et enfin il propose un nombre de registres raisonnable, càd 32 registres de 64 bits, qui peuvent aussi être manipulés comme 16 registres de 128 bits (chez intel: 8 registres de 128 bits en mode 32-bits, 16 registres en mode 64-bit; chez altivec: 32 registres de 128 bits). On peut aussi remarquer que neon a une operation de multiply-add, le genre de trucs que intel n'a pas mis dans SSE, ni dans SSE2, ni dans SSE3, ni dans SSSE, ni dans SSE4v1, ni dans SSE4v2, mais dans AVX (celui des futurs Sandy bridge). Et enfin, les instructions neon ONT trois opérandes: deux termes sources, une destination. Comme altivec, et contrairement à SSE. Là aussi ça permet d'économiser des tonnes de MOVAPS stupides dont la seule raison d'être est d'éviter d'écraser la précieuse valeur d'un registre. C'est encore un domaine où Intel a fini par voir la lumière puisque AVX aura des instructions à trois opérandes.

Voila voila, donc après avoir lu tout ça je me décide, avec entrain, à faire quelques tests puisque j'ai reçu un Toshiba AC100 en début de semaine, le premier netbook à base de ARM Cortex A9 (parfum tegra2), justement pour tester neon. Un netbook fourni avec android, et sur lequel je me suis quand même bien fait chier à installer une ubuntu (c'est pas facile). Et là paf, quand je lance les programmes de test c'est "Illegal Instruction" sur la première instruction neon rencontrée. Bizarre. Effectivement le /proc/cpuinfo ne fait aucune mention de neon .

Et pour cause puisque ces gros tocards de nvidia n'ont pas implementé l'unité NEON dans tegra2. Je l'ignorais.

Je vais donc maintenant frapper ce netbook avec un marteau jusqu'à ce qu'il ne reste plus que quelque misérables copeaux que je balancerai aux chiottes, je tirerai la chasse, puis j'irai me coucher.

malloc lent

Le malloc de macos a la réputation d'être relativement pas rapide, et je viens de le constater sur un petit bout de code, qui passe la majeure partie de son temps à faire du malloc/free (vérifié avec Shark). Sous Snow Leopard, il met 14s à s'executer, alors que sous linux (dans une VM tournant sous macos), le même code, avec une version similaire de g++ et les mêmes optimisations, ne prend plus que 9s , ce qui fait une différence somme toute assez significative ! Voilà qui est édifiant.

xmodmap

Steve jobs est un génie, mais le coup de faire des claviers differents ça n'est pas à 100% une super idée. En particulier quand on veut faire tourner linux ou windows sur un mac. Comme j'ai encore passé un temps dingue a essayer d'avoir un clavier apple qui se comporte a peu prêt correctement sous linux (et qui permet en prime d'avoir le middle-click avec le clavier), voici le .Xmodmap auquel j'ai abouti:

! dans le xorg.conf je pars de : XkbModel macintosh , XkbLayout fr
! curieusement les touches @# et <> sont inversees
! en prime , j'assigne le middle click a 'ISO_Level3_Shift-<'
keycode  94 = at numbersign periodcentered Ydiaeresis periodcentered Ydiaeresis
keycode  49 = less greater lessthanequal greaterthanequal Pointer_Button2 Pointer_Button2
! je remplace le dead tilde par un tilde pas dead
keycode  57 = n N asciitilde dead_tilde asciitilde dead_tilde
! fait en sorte que les deux touches 'option' fonctionnent comme sous mac
keycode 64 = ISO_Level3_Shift
! utilise la touche 'command' en tant que alt/meta
keycode  115 = Alt_L Meta_L
! je vire les nobreakspace parce que ca pue
keycode  65 = space space space space space space

! pas trop compris la... 
remove mod1 = ISO_Level3_Shift
add mod1 = Alt_L

Ôde à mondorescue

Je voulais clôner une debian Lenny installée dans un petit boitier sur un virtualbox tournant sur le mac. On m'a suggeré que Mondo Rescue pourrait être l'outil idéal pour effectuer la transplantation, et il s'est avéré que c'était vrai. Pas besoin de lire 300ko de man page , pas besoin de comprendre des concepts compliqués, on le lance, il pose quelques questions basiques et hop, les partitions de la machine originale sont compressées (avec bzip2, pouah) et backupées dans des fichiers .iso de 4Go. Je les copie sur le mac, créé une machine virtuelle dans virtual box, monte la premiere iso et boote la VM, et hop c'est parti, la debian est clonée dans la VM. C'est tellement chouette et simple que ça m'a inspiré un haiku au nombre de syllabes incertain:

Mondo Rescue,
Tu me laisses
Sur le cul

Cross-compiler en 32-bit sur une debian 64-bit

Un truc que j'aime bien sur le mac c'est la facilité avec laquelle on compile pour du i386, du x86_64, ou du ppc, voire ppc64 (pour celui là c'est fini depuis Snow Leopard, macos 10.5 a été la seule version qui permette de compiler pour ces 4 architectures). Sous windows, avec visual c++, c'est pas super commode mais MS fournit des platform SDK pour i386 et x64 qui sont suffisants (y'a un milliard de dlls là dedans). En plus aussi bien windows que macos savent executer n'importe quelle appli 32-bit sur la variante 64-bit de l'OS. Par contre sous linux, quand on choisit d'installer une distro 64-bit, c'est qu'on a decidé de bannir le 32-bit (qui pue), parce que le 64-bit saitrogénial. Donc par défaut les paquets du genre ia32-libs ne sont pas installés. Les users ne peuvent pas executer simplement n'importe quelle appli 32-bit sur leur gentoo hyper tunée pour aller trop vite parce que les libs sont manquantes. Et c'est la croix et la bannière pour mettre en place un environnement qui permette de compiler des applis non triviales en i386 sur la distro x86_64. En tout cas moi j'ai pas mal galéré mais comme c'était il y a un bout de temps, sur une debian Lenny, j'ai oublié, du coup je vais noter ici un ou deux trucs pour m'en souvenir.

Le probleme, c'est que ia32-libs et ia32-libs-gtk ça ne fournit qu'un sous ensemble des libs qu'on peut avoir besoin d'utiliser... Par exemple, y'a pas libasound (ALSA), c'est ballot. Y'a pas liblo non plus. Etc. Alors comment qu'on fait ?

Dans l'ordre des trucs que j'ai essayé je crois que j'ai tenté l'approche "je compile le cross compilateur, qui va cross-compiler toutes les libs dont j'ai besoin", tout ça sur un core 2 solo 1.2GHz sous-ventilé autant dire que ça a vite tourné à l'échec critique.

Ensuite j'ai mis en place un chroot dans lequel j'ai installé une debian 32-bits, super pénible, pas pratique (faut chrooter pour aller compiler en 32-bit). Mais ça marche et j'ai utilisé cette méthode pendant un certain temps.

Et puis finalement la methode qui marche et qui est relativement pratique, c'est juste de telecharger les .deb i386 à la main, et de les decompresser directement dans /emul/ia32-linux . Par exemple pour liblo:

wget http://ftp.debian.org/debian/pool/main/libl/liblo/liblo0ldbl_0.23-2.2_i386.deb
dpkg -X liblo0ldbl_0.23-2.2_i386.deb /emul/ia32-linux

(et pareil pour le paquet liblo0-dev )

Et ça roulaize.

Processor preferences pane

Je croyais que le panneau de preferences de Tiger qui permettait d'activer ou pas des coeurs du CPU (ainsi que l'hyperthreading) avait disparu lors du passage à Leopard. Et bien que nenni ! Il suffit de l'installer depuis les outils developeurs, il est dans /Developer/Extras/PreferencePanes/Processor.prefPane/ . Truc bizarre, il marque "Unknown Processor" au lieu de Core i7

Noël

Hier j'ai reçu un bel imac 27 pouces core i7, ça poutre un max. C'est mon cadeau de noel que je me suis fait. Par contre en terme de chaleur c'est assez impressionnant, en fait la machine à la forme, et quasiment le dégagement de chaleur, d'un convecteur electrique. Manifestement l'electronique à l'interieur n'est pas en train de cramer, le cpu est à 60° mais on sent que ça produit de la chaleur, même quand on met la main à 10cm devant l'écran. Le micro clavier qui est livré avec est très exigeant en termes de qualité de bureau, je viens de realiser que le mien n'est plus parfaitement plat du coup le clavier est bancal c'est assez désagréable. Et j'ai presque l'impression que l'écran est trop grand, je parcours des kilometres à la souris et je trouve qu'elle n'avance pas assez vite :/

Avoiding objective-c class name conflicts with brute force

The issue is described here : there is no way to control the visibility an objective-c class, and in a plugin context where many plugins might embed variations of a unique library that means conflicts, and ugly crashes. The usual solution, as far as I understand, is just to append some prefix to your own class names. And if you build more than one product, make sure that this prefix is unique for each product. Other solutions are listed here : shared framework, or building classes at runtime but I don't want to consider them for now. So I suggest another solution, which is a brutal but efficient variation of the unique prefix appended to obj-c class names: just append a specific prefix to the names of all you obj-c classes names , lets say "BALAI_BROSSE". Compile your products as usual. And then, for each product, generate a random string of the same length, let's say "OIETDKFJKDSF" , and just do a binary search & replace on the compiled binary, replacing all occurences of BALAI_BROSSE with OEITDKFJKDSF. This step (generating the random string and doing the binary search&replace) can be easily integrated into the build process.

The program I am using to do that is here: binrepl.cc. But feel free to find it dumb and ugly, I'm sure it can be done in one line of perl.

And apparently it works perfectly , I'm not getting anymore the Class Foobar_BALAI_BROSSE is implemented in both foo0 and foo1. One of the two will be used. Which one is undefined. warnings . Which is great.

Déçu par le packagemaker de macos

Le packagemaker c'est l'appli qui permet de fabriquer des installeurs pour macos. Par le passé on ne pouvait pas faire grand chose en ligne de commande, mais maintenant c'est mieux et on peut creer des packages sans dégainer la souris et aller traffiquer dans la gui.

Par contre quand je compare la taille d'un package generé sous macos et celle du même installeur sous windows (fabriqué avec NSIS), la version mac est notablement plus grosse. J'avais mis ça sur le compte des fat binaries puisque la version mac embarque aussi des binaires ppc, mais il semblerait qu'il y ait aussi une autre explication: la compression de packagemaker juste pue. C'est du gzip des année 30. Si je compresse les fichiers du package avec lzma je me retrouve avec une archive 18Mo , alors que le mpkg pour les mêmes fichiers occupe 25Mo :'(

Ainsi j'en appelle à Steve Jobs pour qu'il fixe ça au plus vite ! Merci d'avance !

La dure vie du plugin

C'est pas tous les jours facile d'être un plugin. Le probleme principal du plugin c'est les autres. Parce qu'il n'est pas chargé seul, il est chargé en même temps que d'autres plugins plus ou moins bien elevés, et il doit partager le même espace mémoire qu'eux. Du coup quand un plugin débile commence à faire n'importe quoi et à pourrir le heap, ben c'est pas forcement lui qui plante et qui est accusé d'être buggé. C'est pas non plus toujours facile de convaincre l'auteur du plugin moisi que le bug est de son coté et pas du mien. Et ça ne fait pas non plus toujours plaisir de perdre du temps à aller identifier et corriger les bugs des autres. Bref.

Mais il n'y a pas que l'espace mémoire qui est partagé. Bien souvent, les plugins executent une partie de leur code sur les même threads (cad sequentiellement, l'un après l'autre sur le même thread et pas en parallele). Et ça c'est la porte ouverte à plein d'effets de bords merdiques.

Donc aujourd'hui, l'effet de bord merdique c'est quand un plugin s'amuse à modifier les flags du FPU et a les laisser dans un état completement naze. Par exemple , en construisant sa GUI avec Direct3D: http://blogs.msdn.com/tmiller/archive/2004/06/01/145596.aspx . Car le FPU x87 a un super mode qui force la precision de tous les calculs à 24 bits (cad la simple precision) au lieu de 53 bits (double precision) habituels. Et là c'est le drame, les systèmes linéaires pas trop bien conditionnés commencent à renvoyer des solutions vraiment très fausses, les fonctions exp() etc du runtime c++ commence à devier mechamment , le toolkit de la gui perd completement les pedales et oublie de raffraichir des bouts de gui, affiche une lettre sur deux etc..

j'ai un eeepc

J'ai un eeepc. C'est plutot moche et ça fait un peu cheap, par contre l'autonomie est sympathique.

visual c++ : sux

Bon j'en ai marre de lire un peu partout que gcc est mauvais et que msvc est un excellent compilateur (pareil pour icc). En tout cas pour ce qui concerne le SSE msvc est juste une bouse abominable qui ne sait pondre que du bloat bien lent. Et mon experience est que gcc est presque toujours meilleur que icc sur du code contenant des intrinsincs SSE, malgré toutes les options bling bling de ce dernier. Ca fait plaisir de voir que c'est confirmé ici: http://www.liranuna.com/sse-intrinsics-optimizations-in-popular-compilers/

Stupid script of the day

Here is a python script that I use to invoke the cl.exe compiler (microsoft visual c++) from the cygwin command line. It automatically rewrites the cygwin paths as native windows paths, and replaces the ugly '/foo' options of cl.exe with nice '-foo' options . It is very minimalistic, it could do much more such as trying to map much more gcc-like options to their msvc equivalent ( "-fno-exceptions" with "/EHsc" , "-g" with "/Zi" etc)

http://gruntthepeon.free.fr/cygmsvc

Mini coup de gueule contre std::sort

Aujourd'hui cher blog j'aimerais pousser un petit coup de gueule contre std::sort, dont le comportement n'est pas hyper developper-friendly quand on lui fourni une fonction de comparaison un peu buggée. Figure-toi cher lecteur que lorsque la fonction de comparaison n'est pas tout à fait un StrictWeakOrdering (genre elle renvoie a<b , b<c et a>c), le comportement du std::sort de la libstdc++ est tout simplement de partir en excursion hors des bornes du tableau qu'on est en train de trier. A l'arrivée ça crashe dur. Alors certes je ne doute pas que l'implementation de la libstdc++ est hyper-optimale et plus rapide que son ombre, néanmoins j'apprécierais qu'elle detecte quand la fonction de comparaison n'est pas coherente plutot que d'exploser en vol comme une grosse baleine en allant trier des elements qui ne sont pas dans le tableau. ça me fait râler parce que ça fait plusieurs fois que je me fais avoir par ce truc (oui j'ai du mal a écrire des StrictWeakOrdering sans bugs)

cpufreq sucks for audio

People doing real-time audio processing on Linux are generally very picky about details (real-time kernel with full preemption, fine-tuning or the IRQ priorities, ...). However I did not cross any document mentioning possible drawbacks of CPU frequency throttling. This feature is now available everywhere. Even my quad-core tower spends most of its time at 1.6GHz instead of 2.66GHz. My good old D800 laptop runs at 600MHz when it is idle, and jumps to 1.6GHz when it needs to. But the question is how fast does it transition from 600MHz to 1.6GHz ? This small program does measure it, using the TSC counter. Please note that this does not work on recent CPU as the TSC rate is no more equivalent to the processor speed (that is its rate is now constant).

And finally the result: on my single-core pentium-m, the max cpu frequency is reached after ~0.05 - 0.1 seconds on a desktop kernel (2.6.27) , and 25 ms on the "linux-rt" kernel . Definitively not a negligible latency. That means that if your audio processing load is not smooth, and you have bursts of cpu usage (for example when new notes are played on your great but cpu-hungry softsynth), then you will not be able to use 100% of your cpu, but only 600/1600*100 = 37.5% of its power ! Not great.

But maybe using threads with real-time (SCHED_RR) priority will help ? Just run the program with "-rt" argument. Now the latency is 1 full fucking second on the "normal" kernel, and +INF seconds on the linux-rt kernel !! Not great at all. Of course, cpufreq being a deamon, it has much less chances to get scheduled where a very high priority thread is consuming all cpu. Ok, that is not fair, so you can add a small usleep(10) in the main loop in order to leave it a chance to do its job (the "pthread_yield" is not enough, apparently). And then the latency is back to ~0.1sec on desktop kernel , but still >10sec on rt kernel.

As a conclusion, I would say that doing a 'cpufreq-set -g performance' when your audio software is running is certainly not a stupid idea. Especially on a single-core cpu where the cpufreq deamon is likely to be starved when things start to get hot.