TPL in a real project

31. janvier 2011

Pour mettre un peu en pratique la TPL (Task Parallel Library), j’ai décidé de développer un petit moteur de raytracing.

image

En effet, la technique de raytracing est une technique ultra parallélisable puisque chaque pixel lance son propre rayon et de ce fait est entièrement autonome.

Ainsi si j’ai 800x600 processeurs, je peux lancer en parallèle le shoot d’une image de 800x600.

Bon évidemment c’est de la théorie mais déjà en pratique avec mon core Intel I7 je dispose de 8 cœurs et donc potentiellement de 8 threads totalement indépendants.

L’algorithme général du raytracing consiste donc à faire une double boucle parcourant les x et les y de l’image et lançant un rayon pour chaque pixel.

Cela donne donc à peu prés ceci:

for (int y = 0; y < ScreenHeight; y++)
{
     ProcessLine(scene, y);
}

Grâce à la TPL et sa méthode Parallel.For, la parallélisation est simplissime:

Parallel.For(0, ScreenHeight, y => ProcessLine(scene, y));

Du coup, automatiquement les lignes sont traitées en parallèle.

En termes de performances pour calculer l’image ci-dessus, cela donne:

TPL sur 8 cœurs

38s

Sans TPL (1 seul cœur donc)

89s

Une seule instruction permet un gain de 234%.

Au passage, de nombreux outils sont disponibles pour bien s’intégrer dans une application (je vous renvoie d’ailleurs à ma session sur les interfaces réactives des TechDays (teasing teasing!!)).

Ainsi l’appel principal du raytracer ressemble à ceci:

Task task = Task.Factory.StartNew(() =>
                 {
                   Parallel.For(0, ScreenHeight, y => ProcessLine(scene, y));
                 });
task.ContinueWith(t =>
                 {
                   if (OnAfterRender != null)
                            OnAfterRender(this, EventArgs.Empty);
}, TaskScheduler.FromCurrentSynchronizationContext());

On voit ici l’utilisation de la classe Task qui permet de lancer notre traitement en asynchrone tout en rajoutant un comportement dès que la tâche sera finie avec la méthode ContinueWith. De plus, ContinueWith à l’énorme avantage de pouvoir préciser le contexte de synchronisation. Ainsi nous pouvons faire en sorte qu’une fois notre tâche terminée, un événement soit appelé sur le thread principal et sans passer par le Dispatcher.

En gros, si j’avais voulu la jouer à l’ancienne avec par exemple le ThreadPool, cela aurait donné le code suivant:

ThreadPool.QueueUserWorkItem(o =>
                {
                    Parallel.For(0, ScreenHeight, y => ProcessLine(scene, y));
                    SynchronizationContext.Current.Post(state=> 
                                    {
                                        if (OnAfterRender != null)
                                            OnAfterRender(this, EventArgs.Empty);                         
                                    }, null);
                }, null);
En ce qui concerne le code complet, je le mettrai sur Codeplex dès que j’aurai fini l’intégration des formes non géométriques (à base de meshs donc).

TPL, .Net

Les trois grandes lois du développement

29. janvier 2011

Inspiré par mon maitre à penser (Isaac Asimov), je me suis lancé dans la rédaction de 3 grandes lois applicables sur les développements informatiques.

Dans la masse d’informations et de documentations que l’on retrouve sur Internet, j’ai parfois la sombre impression que l’on perd un peu de vue la réalité pour se retrouver face à des problématiques technico-techniques.

J’en en effet la crainte que l’on se concentre plus sur la technologie que l’on utilise que sur le fonctionnel à développer.

Les 3 grandes lois du développement donneraient donc :

1. Le bon sens en premier lieu conduira chaque choix.

2. Tout ce qui peut améliorer la maintenabilité et l’évolutivité du code doit être employé SAUF si cela va à l’encontre de la première loi.

3. L’esthétique du code sera envisagée SI cela ne va pas à l’encontre de la première ou de la seconde loi.

 

La première loi pourrait aussi se décrire ainsi : PRAGMATISME BORDEL!. En gros si un projet doit être performant et que pour atteindre cette performance il faut faire du code qui ne respecte pas la dernière version du design pattern MVVM à retro-plaque sur mousse organique et bien tant pis! Ce qui compte avant tout c’est le satisfécit du client. Ce qui compte c’est que le logiciel développé corresponde aux attentes du donneur d’ordre.
Bien entendu, dans la majorité des cas, le bon usage des design patterns permet de faire du bon code mais hélas, on retrouve encore trop souvent des solutions développées par des architectes de l’extrême qui tiennent plus de l’usine à gaz que du bon logiciel fiable.

La deuxième loi d’ailleurs va dans ce sens. Utiliser intelligemment les design patterns permet d’industrialiser un développement et de facto de le pérenniser. Il faut juste bien respecter la première loi pour ne pas se lancer dans un développement trop complexe pour un tâche donnée.

Finalement, la troisième loi permet au développeur d’exprimer son besoin de créativité en utilisant toutes les belles technologies ou les beaux design patterns qui font rêver du moment que c’est logique pour le projet et que cela va dans le sens de la fiabilisation.

En conclusion, j’ajouterai juste qu’à mon sens un beau code est un code qui fait beaucoup en peu de lignes. Un beau code c’est un code simple et lisible.

Et comme me disait ma grand mère : “Les commentaires dans le code prouvent juste que ce dernier n’est pas suffisamment clair par lui-même. Un bon code est un code compréhensible directement, sans autre artifice.”. Il n’y a pas à dire, elle s’y connait Mamie.

.Net, Philo

Nova et Kinect

27. janvier 2011

Une petite vidéo de l’intégration de Kinect avec Nova:

 

Oui, ca roxxe Sourire

Nova ,

DOT NET Quizz 2011 on BeyondRelational

19. janvier 2011

Sur le site beyondrelational.com, vous aurez le plaisir (que dis-je! la joie!) de trouver un quizz sur le thème de .NET.

J’ai été contacté pour fournir une question du quizz et il se trouve que c’est aujourd’hui que cette question s’est activée.

Je vous donne donc le lien si vous souhaitez participer à ce jeu purement intellectuel (comprenez : “Non, il n’y a pas de Kinect à gagner”).

http://beyondrelational.com/quiz/dotnet/general/2011/questions/using--operator.aspx

.Net

Collecto 1.7

9. janvier 2011

Collecto 1.7 est désormais disponible sur le marketplace.

Sauf que, suite à une erreur du marketplace, cette version est “dissociée'” de la 1.6.

Donc si vous voulez mettre à jour, pas de soucis, voila la procédure à suivre:

- Lancer Collecto 1.6
- Vérifier dans le menu Réglages(Settings) que vous êtes bien connecté 
- Le fermer réellement (sans passer par la touche WIndows)
- Désinstaller Collecto 1.6
- Installer Collecto 1.7 et utiliser toujours le même login/pass
- Le tour est joué!

Au programme de cette nouvelle version:

* Les éléments récents peuvent être filtrés
* Support de Amazon.ca
* Correction de bugs mineurs

Et bien sur le deep link: http://social.zune.net/redirect?type=phoneApp&id=ef2b8553-0a18-e011-9264-00237de2db9e

Collecto, Windows Phone

Une excellente année de la part de toute l’équipe Bewise

6. janvier 2011

Je me joins à mes chers collègues mais néanmoins amis pour vous souhaiter à tous (encore) une excellente année 2011 avec pleins de .NET, de TPL, de DirectX, de XNA, de WP7, de WPF ou de Silverlight dedans.

 

S6 (2)

Bewise

Le truc à la con du jour : GridSplitter et Grid, comment sauver les tailles des colonnes?

5. janvier 2011

Alors voila le topo: j’ai une grid avec des splitters dedans pour changer la taille des colonnes:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition MinWidth="200" Name="column0"/>
        <ColumnDefinition MinWidth="200" Name="column1"/>
        <ColumnDefinition MinWidth="200" Name="column2"/>
    </Grid.ColumnDefinitions>
    <Rectangle Grid.Column="0" Fill="Red"/>
    <Rectangle Grid.Column="1" Fill="Blue"/>
    <Rectangle Grid.Column="2" Fill="Green"/>
    <GridSplitter Grid.Column="0" VerticalAlignment="Stretch" 
HorizontalAlignment="Right" Width="4"/> <GridSplitter Grid.Column="1" VerticalAlignment="Stretch"
HorizontalAlignment="Right" Width="4"/> </Grid>

Je voudrais à la fermeture sauver la taille de mes colonnes et pouvoir les refixer lors du chargement suivant.

Du coup, bêtement, lors du chargement je faisais ça:

column0.SetValue(ColumnDefinition.WidthProperty, new GridLength(300));
column1.SetValue(ColumnDefinition.WidthProperty, new GridLength(300));
column2.SetValue(ColumnDefinition.WidthProperty, new GridLength(300));

Et bien je vous le donne en mille : ça ne marche pas! En effet, lorsque je bouge par la suite mes colonnes, la taille des colonnes semblent vouloir rester constante et le comportement global est inadapté.

La solution, comme toujours, est simple. En effet, les colonnes ont une propriété Width (et Height) qui n’est pas qu’un double mais un objet de type GridLength. Or ce dernier permet d’exprimer des tailles absolues (comme ci-dessus) mais aussi des tailles relatives (le célèbre “300*”).

Ainsi, pour conserver le comportement des colonnes tout en remettant les tailles de départ correctement il suffisait d’exprimer les tailles en relatif:

column0.SetValue(ColumnDefinition.WidthProperty, new GridLength(300, 
GridUnitType.Star)); column1.SetValue(ColumnDefinition.WidthProperty, new GridLength(300,
GridUnitType.Star)); column2.SetValue(ColumnDefinition.WidthProperty, new GridLength(300,
GridUnitType.Star));

WPF

Année 2011

5. janvier 2011

C’est d’un bateau monumental mais je vous souhaite tout de même à tous une EXCELLENTE ANNEE 2011.

Mes objectifs pour 2011 pour ce blog : continuez comme en 2010 Sourire avec beaucoup de techniques et un peu de philo.


Je vous remercie également de votre fidélité et de vos nombreux mails de soutien!

 

Bonne-Annee-2011-01

Divers