PROJET AUTOBLOG


Sam & Max: Python, Django, Git et du cul

Site original : Sam & Max: Python, Django, Git et du cul

⇐ retour index

Mise à jour

Mise à jour de la base de données, veuillez patienter...

10 excellents films peu connus

mercredi 16 octobre 2013 à 17:26

Après la thématique des séries, petite aparté pour parler de 10 films qui méritent de votre temps, en cette époque où tellement de bouses essayent de vous le faire perdre en vous faisant payer pour ça.

Dogma

Ce film est l’archétype du bijou inconnu.

D’abord, un casting monstrueux : Matt Damon, Ben Affleck, Alan Rickman, Chris Rock et Alanis Morissette (qui joue Dieu, si si).

Ensuite, un scénario complètement barré : Dieu (qui est une femme), a disparu. Deux anges qui ont tendance à massacrer un peu tout ce qui passe vont tenter d’en profiter pour baiser le système, ce qui pourrait causer quelques souci dans la stabilité du monde. Du coup on envoie le 13eme prophète, un oublié de la Bible parce qu’il est noir, filer un coup de main à la petite-petite-petite descendante de Jésus pour rétablir tout ça.

Les dialogues sont fantastiques, les personnages sont tous uniques et hauts en couleurs. Ai-je mentionné que c’était drôle ?

Le prestige

Bien avant de faire the Dark Knight, Christopher Nolan était déjà un réalisateur de génie avec des films uniques comme Memento. Mais bien au dessus de tout ça, bien au dessus de tous ses films en fait, se trouve le Prestige.

Déjà vous avez Wolverine et Batman dedans, et ça, ça claque. Et surtout, vous allez être embarqués dans une histoire que vous ne pourrez prédire à aucun moment. Aucun cliché, aucune manière de prédire ce qui va arriver. Vous allez vous enrichir, apprendre, et plonger dans les méandres de ce scénarios pourtant très simple, mais intensément mis en scène. Un duel entre deux prestidigitateurs s’étale sur plusieurs années, et vous allez découvrir, pas à pas, le prix du prestige.

Chat noir, chat blanc

C’est Serbes, c’est barré, c’est joyeux, c’est hyper dynamique et ça vous prend complètement au dépourvu. Attaque de trains d’essence, mariage forcé, jongle avec des grenades, suicide et résurrection. Les rebondissements ne s’arrêtent jamais, le tout dans une bande son qui va vous faire danser la Mouchkivtche Blévédienne.

Si vous avez besoin d’un dépaysement, c’est le moment.

La cité des enfants perdus

Les gens connaissent Jeunet pour Amélie Poulain, et parfois, pour Delicatessen. Beaucoup plus rarement pour le étonnement bon Alien 4. Et quasiment jamais pour la cité des enfants perdus.

Chef d’œuvre visuel, je ne vous le recommanderais néanmoins pas durant les phases de déprime, car c’est un film très glauque, une marrais cinématographique psychologiquement violent, parfois dur à encaisser : un vieux scientifique vivant sur une plateforme pétrolière entourée de mines marines et de ses clones plus ou moins ratés, n’arrive pas à rêver. Pour y pallier, il kidnappe des nouveaux nés et tente de leur voler leurs rêves, n’obtenant que des cauchemar. Une frêle fille maline et un géant un peu bête trouvent une cause commune pour aller s’y aventurer…

Les Looney Tunes passent à l’action

Je m’attendais à un Space Jam, et je suis tombé sur un Qui veut la peau de Roger Rabbit. Comme quoi il reste parfois un soupçon de créativité chez les majors. Mais vraiment au fond de l’assiette, hein.

Bref, c’est du dessin animé incrusté dans du film, à la Mary Poppins / l’Apprentie sorcière / Peter et Eliot le dragon. Les bons trucs à l’ancienne quoi. Mais modernisé. C’est cartoonesque dans l’hum(o|e)ur, avec pas mal d’auto-dérision sur Warner Bros, les grosses compagnies en général et les block busters en particulier.

Jusqu’en enfer

J’ai hésité à mettre Chambre 1408, mais ce dernier (comme beaucoup de bons films avec Cusack genre War, inc…), n’est pas un film qui fait peur. Or je voulais faire un top 10 un peu diversifié. Mais franchement, combien de films d’horreur font peur ? Presque aucun. En fait, la scène de Dumbo bourré (si, si, regardez à nouveau le film…) m’a bien plus effrayé que les merdes d’Insidious ou Paranormal activity. Et certes, Chucky, Jason, L’exorciste ou Freddy sont des classiques géniaux. Mais ils ne font pas vraiment peur. Même les bonnes surprises récentes (hello la cabanes dans les bois !) sont divertissantes, pas effrayantes.

Jusqu’en enfer m’a fait sursauté bien des fois. J’ai vraiment senti l’angoisse s’installer, j’ai senti la panique des personnages, j’ai été trainé dans la spirale maléfique de ce film là où Dark Water m’a vainement tiré un bâillement.

Le scénario a en fait peu d’importance. Ce qui est génial, c’est le rythme. La descente. La progression lugubre bien maîtrisé, avec une subtilité que les productions américaines ont rarement. Et des acteurs qui soutiennent chaque plan, car il n’y a rien de plus facile à raté qu’une scène où l’on joue la terreur. Ce film est brillant de par sa progression : il commence tranquillement, et vous prend par derrière au plus mauvais moment. Même quand vous vous y attendez, il n’y a rien à faire.

Et hop, le film est en entier sur Tutube :

Explorers

A cheval entre les Goonies et Jumanji, ce film qui a un poil vieilli va vous servir de madeleine des années 80. Souvenez-vous : retour vers le future, ghostbuster, gremlins, et des réalisateurs qui ne violaient pas encore les symboles de la jeunesse de leur public avec des Super 8 et Indiana Jones 4.

Explorers, ce sont des gamins qui rêvent d’un plan de circuit electronique, et qui le construisent, pour s’apercevoir qu’il peut générer une bulle dans laquelle ont ne ressent aucune inertie, et qui peut traverser toute matière, se déplaçant avec peu d’énergie, transportant un fort poids. Et là commence une bonne aventure old school, avec des gosses bordéliques (franchement, vous avez vu les chambres bien rangés qu’ils ont dans les films actuels les gamins ?) avec des réactions de gosses et des préoccupations de gosses. Pas d’ados, pas de faux adultes. De gosses. Et des costumes ridicules.

Atomik Circus

Si je ne peux pas vraiment vous décrire ce qu’est Atomik Circus, c’est parce que je m’en sens incapable. Ce film n’appartient à aucun genre, ne suis pas vraiment de logique, et n’a pas le goût de quoique ce soit de testé auparavant.

Dire pourquoi j’aime ce film me semble relever tout autant de impossibilité rédactionnelle : l’ambiance unique ? L’humour (très) noir ? Le côté imprévisible ? Les personnages tarés ?

Attendez, je vous traduis le résumé de IMDB, vous allez comprendre ce que je veux dire :

James Bataille s’échappe de prison pour retrouver sa fiancée Concia. Mais à son retour des poulpes aliens viennent jouer un jeu de massacre. Après une bataille bien chanceuse, James et Concia s’échappent dans un monde parallèle.

Et bien sachez mes amis, que ceci, bien que somme toute correcte, ne vous apprend RIEN sur le film. Et j’en veux pour preuve cet extrait :

Tentez le coup. Avec des amis ouverts d’esprit :-)

Heathers

Ah, les teen movies. Ça ne peut pas être bon pas vrai ? Je veux dire, on en a bouffé du vampire, du loup garou, des demi-machin et des abrutis complets. A croire que le genre est maudis !

Mais pas du tout ! Le péril jeune, The Breakfast club et Ferris Bueller’s Day Off prouvent au contraire qu’on peut taper dans l’ado ET être intéressant. L’astuce, c’est de considérer les mineurs comme des être humains, comme les femmes, les juifs et les autistes.

Et la palme des répliques les plus trash revient à….

Fuck me gently with a chain saw

La peur au ventre

Comment trouver un comparatif pour La peur au ventre. Pour le rythme, je pourrais invoquer les merveilleux Arnaque, crime, et botanique, Slevin ou Snatch. Clairement, il y aussi une inspiration d’Alice au pays des merveilles (restez pour le générique de fin, ça vaut le coup) pour le côté fuite dans un monde délirant. Et pour le côté transgressif et dépaysant, peut être un peu du surprenant Old Boy.

Je ne m’attendais pas du tout, mais alors, pas du tout, à ce que la peur au ventre me plaise. Mon pote me l’avait très mal vendu, et le synopsis est à chier.

Mais voilà, encore un scénariste qui a travaillé ses rebondissements et ses personnages. Encore des acteurs qui prennent leurs rôles très à cœur. Et une petit touche de magie qui donne à ce thriller une atmosphère bien à lui, de la personnalité et de la force.

Allez, finissons ce billet avec un peu de pédophilie, sinon on ne serait pas sur Sam et Max :

Par contre les commentaires les plus populaires sur youtube sont vraiment flippant.

flattr this!

Les time zones en Python

mardi 15 octobre 2013 à 20:23

Si vous suivez un peu le blog, vous savez comment manipuler les dates en Python. Et c’est trop cool. Parce que le temps, c’est quelque chose de difficile en programmation, comme la gestion des monnaies ou la traduction d’une interface.

Mais notre article ne traite pas des time zones, c’est à dire de la gestion des fuseaux horaires. La raison est très simple, Sam est une grosse feignasse, et comme c’est un sujet super galère, il l’a soigneusement évité, vous renvoyant à l’usage de pytz. Démerdez vous.

Qu’est-ce qui a changé ? Le sujet est-il devenu plus simple ? Sam a-t-il un regain de motivation ? Le fait de parler de lui à la 3eme personne est-il signe de sénilité ?

Bien sûr que non, c’est simplement que je suis tombé sur arrow, une lib Python qui résout le problème. Pour faire simple, c’est presque exactement la lib que j’avais commencé à coder pour la gestion du temps. Sauf que le mec, lui, il l’a terminé, alors que la mienne, elle est au fin fond d’un repo git poussiéreux depuis 8 mois.

Bref, laissez tout tomber, n’installez plus dateutil, pytz et autres libs que j’ai pu vous recommander par le passé (elle sont incluses et abstraites par arrow). Faites juste :

pip install arrow

Tout commence par l’UTC

Comme pour la gestion des encodings, la gestion des dates se fait en utilisant une base commune. Pour l’encoding, c’est unicode, pour les dates, c’est UTC.

Donc, si vous prévoyez de gérer différents fuseaux horaires dans votre programme, TOUT votre programme – j’ai dit TOUT – doit manipuler exclusivement des dates en UTC.

Comme avec l’encoding, l’idée est la suivante :

Ceci suppose donc que :

Avec arrow, c’est simplissime…

Si vous créez une date vous même, il suffit de toujours le faire en UTC :

>>> import arrow
>>> maintenant = arrow.utcnow() # heure et date actuelle en UTC
>>> print(maintenant)
2013-10-15T17:15:19.139000+00:00
>>> from datetime import datetime
>>> date_de_sortie_des_goonies = arrow.get(datetime(1985, 12, 4), 'US/Pacific')
>>> print(date_de_sortie_des_goonies)
1985-12-04T00:00:00-08:00
>>> date_de_sortie_des_goonies = date_de_sortie_des_goonies.to('utc')
>>> print(date_de_sortie_des_goonies)
1985-12-04T08:00:00+00:00
Là, on a des dates uniquements en UTC.

Si vous importez une date, c’est très simple également :

>>> arrow.get(1367900664) # un timestamp marche..
<Arrow [2013-05-07T04:24:24+00:00]>
>>> arrow.get('1367900664') # ... même en string
<Arrow [2013-05-07T04:24:24+00:00]>
>>> arrow.get(1367900664.152325) # ... ou en float
<Arrow [2013-05-07T04:24:24.152325+00:00]>
>>> arrow.get('2013-09-30T15:34:00.000-07:00').to('utc') # parser une date standard...
<Arrow [2013-09-30T22:34:00+00:00]>
>>> from dateutil import tz # pour parser une date custo
>>> arrow.Arrow.strptime('2013-05-05 12:30:45', '%Y-%m-%d %H:%M:%S', tz.gettz('Paris/Europe'))
<Arrow [2013-05-05T12:30:45+00:00]>

Tout ça renvoie de l’UTC.

Et quand vous voulez afficher une date, vous pouvez tout simplement la reconvertir vers la timezone de votre choix avec la méthode to() et la formater comme avec format()

Stockage des dates

Quand on stocke une date (dans une base de données, un fichier, etc), il faut se demander quel est le but du stockage. Si le but est de stocker la date d’un événement, mettez la date en UTC. Un timestamp suffit, ou alors la représentation YYYY-MM-DD hh:mm:ss. Par contre, si vous voulez stocker une date liée à un événement et un lieu (par exemple un rendez-vous d’affaire ou le décollage d’un avion), stockez la date en UTC avec sa timezone dans un champ à côté, sinon vous serez bien baisé quand vous voudrez la ressortir.

Ah oui, et réglez toujours tous vos serveurs sur UTC. Toujours.

En bonus

On peut obtenir toutes les infos utiles sans tourner autour du pot :

>>> a = arrow.utcnow()
>>> print(a.datetime)
2013-10-15 17:48:28.335000+00:00
>>> print(a.timestamp)
1381859308
>>> print(repr(a.naive)) # on accès à l'objet datetime au cas où...
datetime.datetime(2013, 10, 15, 17, 49, 25, 515000)
>>> print(a.tzinfo) # ... et à l'objet tzinfo
tzutc()
>>> print(a.year, a.hour)
(2013, 17)

Et on peut faire des replacements et des calculs flous, comme avec dateutil :

>>> a = arrow.utcnow()
>>> print(a.format('DD, MMMM', locale='fr_FR'))
15, Octobre
>>> a = a.replace(day=30)
>>> print(a.format('DD, MMMM', locale='fr_FR'))
30, Octobre
>>> a = a.replace(days=+1)
>>> print(a.format('DD, MMMM', locale='fr_FR'))
31, Octobre
>>> a = a.replace(months=-1)
>>> print(a.format('DD, MMMM', locale='fr_FR'))
30, Septembre

Faire de l’affichage relatif :

>>> before = arrow.utcnow().replace(hours=-3)
>>> before.humanize(locale='Fr_fr'))
'il y a 3 heures'

Bref, arrow, c’est de la bombe baby !

flattr this!

Dites non aux animations 3D

lundi 14 octobre 2013 à 18:07

Juste parce que vous pouvez ne veut pas dire que vous devez, et le fait que maintenant la plupart des navigateurs supportent des belles transitions 3D ne signifie certainement PAS que vous devriez les utiliser.

En ergonomie, une règle essentielle est de ne pas mettre ou faire de choses qui n’ont pas de valeur ajoutée pour l’utilisateur.

L’esthétique est certes, en soi, une valeur ajoutée. Mais il faut considérer deux choses :

Pour les animations 3D, la réponse est clairement NON, dans 99% des cas.

D’abord, généralement l’animation est lente, ne serait-ce que pour que le mec devant son écran puisse la voir. Vu le temps qu’on passe à se faire chier à rendre une app plus rapide et fluide à utiliser, pourquoi voulez-vous, VOLONTAIREMENT et ARTIFICIELLEMENT faire patienter votre utilisateur 400ms de plus devant le slide à cube rotatif pour voir la photo suivante ?

Ensuite, malgré l’énorme progrès de nos navigateurs, ça bouffe beaucoup de ressources. Bien sûr, quand vous testez sur votre machine quad core avec chrome et un tab ouvert, c’est parfaitement fluide. Mais il suffit de jouer sur seul de ces paramètres pour que ça ne le soit plus :

Dans la vraie vie vivante, ce sont plusieurs de ces paramètres qui rentrent en compte, presque systématiquement. Et je ne vais même pas vous parler de ceux qui utilisent IE avec plein de toolbar sur une machine infectée jusqu’à la moelle. Qui sont, je le rappelle, la majorité des personnes dans le monde. Pas forcément la majorité de votre cible, mais tout de même…

…vous êtes une putain de page Web, vous ne pouvez pas pré-supposer de ce que l’utilisateur fait et dans quel contexte.

Bref, à moins d’avoir une app avec une connotation visuelle primordiale, par exemple un jeu vidéo, arrêtez avec ces foutues transitions 3D, ça rend votre app inutilisable. Les transitions 2D suffisent largement à améliorer l’ergonomie et l’esthétisme d’une page, et elles bouffent beaucoup moins.

Merci

flattr this!

Si tôt revenu, si tôt repartu

jeudi 10 octobre 2013 à 10:50

Avec l’article goulu d’hier, certains ce sont dit, “chouette, enfin, les articles forts, beaux et puissants de Sam et Max” reviennent à la charge.

Mais je suis au regrès de vous annoncer que je me casse pour 4-5 jours pour aller courrir nu dans les bois. Ma bite ne captant pas la 3G, il n’y aura pas d’article pendant ce temps.

Donc je vous dis à la semaine…

… prochaine !

flattr this!

La différence entre la programmation asynchrone, parallèle et concurrente

jeudi 10 octobre 2013 à 00:08

On parle un peu partout de programmation non bloquante ces temps-ci. NoSQL a remis le map/reduce au goût du jour, et PAF, on vous sort le mot clé parallélisation pour vous en vendre une tetrachiée. Les partisants de NodeJS vont crier “asynchrone”, parce que c’est ce que Javascript sait faire de mieux. Et on murmure dans les coins que la robustesse d’Erlang tient dans ses acteurs qui travaillent de manière concurrente dans la VM.

Ok, donc tout ça, ça à l’air de faire la même chose, c’est à dire de faire plusieurs choses en même temps, sans bloquer.

Donc c’est pareil ?

Non. En fait c’est une question de point de vue : non bloquant dans quel contexte ?

Si c’est l’IO, c’est asynchrone

Pour rappel, l’IO (Input/Ouput), c’est toute activité qui implique que des données entrent et sortent de votre programme : saisie utilisateur, print sur un terminal, lecture sur une socket, écriture sur le disque, etc. Une opération I/O a plusieurs caractéristiques :

La plupart des programmes bloquent quand ils effectuent une opération I/O. Par exemple, si vous faites ceci en Python :

import urllib2
 
# télécharge et affiche le contenu de la page d'acceuil de sam et max
print(urllib2.urlopen('http://sametmax.com').read())
print("Coucou")

La ligne print("Coucou") ne s’exécutera pas tant que la ligne précédente n’aura pas terminé de s’exécuter. Dans ce cas ce n’est pas très grâve, mais dans ce cas là :

import urllib2
 
 
mille_urls = obtenir_liste_de_mille_urls()
contenu = []
 
# télécharge et sauvegarde dans une liste
# le contenu de chacune des 1000 urls
for url in mille_urls:
	contenu.append(urllib2.urlopen(url).read())

Chaque url est téléchargée une par une, et comme Internet, c’est vachement lent (300 ms X 1000, ça fait 5 minutes, mine de rien), votre programme va prendre un temps fou. Et pour rien en plus, car votre programme va passer la majeure partie du temps à ne rien faire ! En effet, 99% du temps de votre programme est passé à attendre qu’Internet réponde, pendant que votre CPU se touche les noix.

La programmation asynchrone est une réponse à cela : au lieu d’attendre que se finissent les entrées et les sorties, le programme continue de fonctionner.

Une autre problématique se pose alors : comment obtenir le résultat de l’opération d’I/O, puisqu’on ne sait pas quand il va arriver et qu’on attend pas qu’il arrive ?

C’est là que les systèmes synchrones font un peu de magie. En vérité, une partie du programme attend, mais discrètement, en arrière plan, au niveau de ce qu’on appelle une boucle d’événements (“events loop”), c’est à dire une boucle infinie qui check régulièrement si une opération I/O ne s’est pas terminée.

Cette boucle est invisible pour vous, votre programme continue de tourner. Mais si une opération I/O envoie des données, alors l’events loop va réagir.

Ca a l’air compliqué, mais en fait, c’est, la plupart du temps, juste une histoire de callback (si la notion vous échappe, je vous renvois à l’article dédié…). Par exemple en Javascript :

var mille_urls = obtenir_liste_de_mille_urls();
var contenu = [];
 
# notre callback qui va permettre d'ajouter 
# le contenu téléchargé à notre liste
var callback = function(data) { 
      contenu.push(data);
};
 
# Bon, j'utilise jquery pour simplifier le code...
# On boucle sur les milles URL
$.each(mille_urls, function(index, url) {
  # On télécharge le contenu, MAIS comme
  # $.get est naturellement non blocante,
  # elle ne va pas attendre qu'internet 
  # réponde pour continuer la boucle, et
  # donc on pourra attendre plusieurs réponses
  # en même temps. Pour avoir le résultat de 
  # chaque réponse, on passe un callback qui 
  # va être appelé quand la réponse arrive.
  $.get(url, callback);
 
});

Comprenez bien la subtilité : à tout moment, il n’y a qu’UN SEUL process javascript qui s’éxécute. Il n’y a pas deux traitements, pas de threads, pas de processus parallèles, rien de tout ça. Simplement, Javascript n’attend pas la réponse de sa requête pour faire la requête suivante, il continu sur sa lancée, et donc peut optimiser les temps d’attente en attendant plusieurs choses en même temps.

Javascript utilise massivement des API asynchrones, c’est au cœur du langage, il n’y a aucun effort à faire pour cela. A l’inverse, Python est synchrone par nature, et il faut vraiment se faire chier pour obtenir un algo asynchrone. Ceci changera avec Python 3.4 qui accueillera tulip dans la stdlib, afin de se moderniser sur ce point. En attendant, si vous voulez faire de l’asynchrone en Python, vous pouvez voir du côté de gevent, monocle ou Tornado. L’alternative est d’utiliser des threads ou des processus séparés, ce qui ne demande rien à installer, mais est un peu verbeux, et est moins performant.

Souvenez-vous que l’I/O, c’est toute entrée et sortie du programme. Un clic sur un bouton, c’est une entrée, mettre à jour un élément du DOM dans le navigateur, c’est une sortie. La programmation asynchrone est donc importante pour la réactivité des programmes.

Si un algorithme peut répartir son travail en plusieurs bouts, c’est parallèle

Par exemple, vous avez 1000 images en haute définition à traiter : il faut les redimensionner, les mettre en noir et blanc et ajouter une ombre sur les bords. Là, la partie de votre programme qui prend le plus de temps, c’est le traitement des images, pas l’I/O, et donc c’est le CPU. Par exemple, en Python :

for image in obtenir_liste_images():
	# I/O
	data = lire_image(image) 
 
	# gros du travail
	redimensioner(data)
	mettre_en_noir_et_blanc(data)
	ajouter_ombre(data)
 
	# I/O
	ecrire_image(data, image)

Si vous avez plusieurs ordinateurs, une manière de paralléliser le travail est de mettre 500 images sur l’un, et 500 images sur l’autre, et de lancer le script sur chaque ordi.

Si vous avez plusieurs processeurs dans votre ordi (ce qui est le cas de tous les ordis modernes, et plus seulement les super-calculateurs comme il y a 10 ans), vous pouvez aussi paralléliser le travail sur une seule machine : chaque processeur va s’occuper d’une partie du taf.

Bien entendu, vous pouvez lancer le script 2 fois, mais cela ne marche que sur des travaux simples comme celui là. Et ça suppose que vous connaissez le nombre de CPU que vous voulez faire travailler à l’avance.

Une manière de faire plus propre est d’utiliser des threads ou des processus séparés. En Python, le thread ne servirait à rien, car on se heurterait au GIL, le fameux global interpréteur lock, qui fait qu’une VM n’utilise qu’un processeur, quoi qu’il arrive. Les threads ne sont donc utiles (en Python), que pour l’I/O. Par contre on peut utiliser plusieurs processus :

from multiprocessing import Process
 
def traiter_les_images(debut, fin):
 
 for image in obtenir_liste_images()[debut, fin]:
	# I/O
	data = lire_image(image) 
 
	# gros du travail
	redimensioner(data)
	mettre_en_noir_et_blanc(data)
	ajouter_ombre(data)
 
	# I/O
	ecrire_image(data, image)
 
# On crée deux processus, un pour traiter les 500 premières images,
# un pour traiter les images de 500 à 1000
p1 = Process(target=traiter_les_images, args=(0, 500))
p2 = Process(target=traiter_les_images, args=(500, 1000))
# On les démarre, ils se séparent alors du programme pour
# devenir indépendant
p1.start()
p2.start()
# on dit au programme d'attendre la fin des deux processus
# CE programme bloque ici, mais les deux processus, eux,
# ne bloquent pas.
p1.join()
p2.join()

Dans cet exemple, il y a TROIS processus : votre programme Python, et les deux processus qui vont traiter les photos, qui consistent ni plus ni moins en la fonction traiter_les_images() qui a maintenant un process pour elle toute seule.

La plupart des langages ont ce genre de mécanisme pour faire du travail en parallèle. Java utilise les threads par exemple. Javascript utilise les Web Workers.

Nous traitons des données de plus en plus massives (jeux vidéos, encoding divx, retouche d’images, montage de sons…), et maîtriser la parallélisation permet donc d’optimiser les ressources de nos machines modernes afin d’être toujours plus efficace.

Si il y a plusieurs entités indépendantes, c’est concurrent

Si vous avez un serveur et un client, c’est de la programmation concurrente. Si vous avez un module qui s’occupe des I/O utilisateurs, un qui s’occupe de la base de données et un qui surveille le comportement de l’OS, dans des processus séparés, et qui communiquent entre eux, c’est de la programmation concurrente.

La programmation concurrente suppose que chaque acteur de votre système est indépendant et possède son propre état. Idéalement, les acteurs sont capables de communiquer entre eux. Généralement, ils partagent une ressource à laquelle ils doivent accéder, par exemple un fichier de log. Et c’est là qu’il faut faire attention : certaines ressources ne sont pas faites pour êtres utilisées en même temps par plusieurs process. C’est pour ça qu’on parle d’accès concurrent comme d’un gros problème en informatique.

Un exemple de programmation concurrente en Python serait d’avoir un process qui regarde régulièrement si il y a des mails, et les sauvegarde. Si il reçoit un message suspect, il envoie le message à un autre process, un anti-virus, qui en plus de surveiller l’ordi, peut désinfecter le mail. Exemple :

from multiprocessing import Process, Queue
 
entree_traiteur_de_mail = Queue()
entree_anti_virus = Queue()
 
def traiter_les_mails():
 
	# Les processus qui tournent continuellement
	# en arrière plan sont juste boucle infinie
	while True:
		mail = obtenir_mail()
		# Si un mail est suspect, on l'envoie
		# au processus de l'anti-virus, 
		# et on attend qu'il nous le renvoie
		# tout propres.
		# Les deux processus sont indépendant,
		# ils fonctionnent l'un sans l'autre et
		# ne sont pas dans la même VM.
		if mail_est_suspect(mail):
			entree_anti_virus.put(mail)
			mail = entree_traiteur_de_mail.get()
		sauvegarder_mail(mail)
 
 
def anti_virus():
 
	while True:
		# L'anti-virus vérifie périodiquement 
		# s'il n'a pas un mail à nettoyer,
		# mais n'attend que 0.01 seconde, et si
		# rien ne se présente, continue son 
		# travail.
        try:
        	# Si il y a un mail à désinfecter,
        	# il le nettoie, et le renvoie
        	# au processus de traitement de mails.
            mail = entree_anti_virus.get(0.01)
            desinfecter_mail(mail)
            entree_traiteur_de_mail.put(mail)
        except TimeoutError:
            pass
        # L'anti-virus ne fait pas que desinfecter 
        # les mails, il a d'autres tâches à lui
        verifier_virus_sur_system()
 
 
# On lance les process. La plupart du temps, il n'y a 
# pas de mail suspect, et donc les deux processus
# n'en bloquent pas. En cas de mail suspect ils bloquent
# le temps d'échanger le mail entre eux.
process_anti_virus = Process(target=traiter_les_mails)
process_traitement_mail = Process(target=anti_virus)
process_anti_virus.start()
process_anti_virus.start()
process_anti_virus.join()
process_traitement_mail.join()

La programmation concurrente est donc une question d’architecture : vous êtes en concurrence ou non si vous décidez de répartir votre code entre plusieurs acteurs indépendant ou non. Les acteurs peuvent avoir des tâches distinctes, et ne pas se bloquer, mais communiquer sur les tâches communes. L’avantage de la programmation concurrente, c’est sa robustesse : si un process plante, le reste de votre programme continue de fonctionner. C’est pour cette raison qu’Erlang, un langage connu pour créer des systèmes increvables, base toute sa philosophie là dessus : un programme Erlang est composé de milliers d’acteurs communiquant entre eux par messages.

Hey, mais, attends là !

Ton exemple de programmation parallèle, c’est aussi une exécution concurrente. Et puis si on fait pleins de processus, pour faire la même tâche d’I/O, ils ne se bloquent pas entre eux, donc c’est non bloquant sur l’I/O, c’est asynchrone !

Allez-vous me dire, fort intelligement. Car nous avons des lecteurs intelligents.

Hé oui, effectivement, ce sont des notions qui se chevauchent. Comme je vous l’ai dit, c’est une question de point de vue. Si on se place du point de vue de l’algo, on peut paralléliser le traitement, ou non. Et il y a plusieurs manières de paralléliser. Si on se place du point de vu de l’I/O, on peut bloquer ou non, et alors on est dans de l’asynchrone. Si on se place du point de vu des acteurs, on peut en avoir plusieurs indépendants ou non, alors on est en concurrence.

En fait, même plusieurs acteurs qui communiquent entre eux sont considérés comme étant chacun en train de faire de l’I/O, avec les autres…

Bref, ces 3 termes, c’est de la sémantiques. Au final, ce qui importe, c’est que vous compreniez les enjeux qu’il y a derrière pour écrire un programme qui fasse son boulot comme il faut, et finisse en temps et en heure.

flattr this!

Error happened! 0 - count(): Argument #1 ($value) must be of type Countable|array, null given In: /var/www/ecirtam.net/autoblogs/autoblogs/autoblog.php:428 http://www.ecirtam.net/autoblogs/autoblogs/sametmaxcom_a844ada43a979e3b1395ab9acb6afafb84340999/?132 #0 /var/www/ecirtam.net/autoblogs/autoblogs/autoblog.php(999): VroumVroum_Blog->update() #1 /var/www/ecirtam.net/autoblogs/autoblogs/sametmaxcom_a844ada43a979e3b1395ab9acb6afafb84340999/index.php(1): require_once('...') #2 {main}