Twitter

J’avais un problème la semaine passée concernant le webBrowser. Il était indispensable pour rechercher une personne sur twitter. Normalement on utilise le protocole oAuth pour les échanges de token afin de pouvoir « s’identifier » mais il est possible de passer cette étape d’échange pour pouvoir accéder aux requêtes du serveur. En fait, lors de l’enregistrement de l’application, on reçoit une clé API, et une clé secrète mais on reçoit également un Token et un AccessToken qu’il est possible de coder en dur, ce qui évite l’interaction avec le WebBrowser.         \o/

Mort au combat …

Comme les problèmes n’arrivent jamais seuls, voilà le petit message d’erreur que le panneau de configuration Nvidia m’affiche… Alors que j’ai (avait) une 8800 GTX! Pour info, les drivers sont à jour et à l’heure où je vous parle mes écrans restent en veille quand j’allume le pc. Je pense que ça sent le rachat de carte graphique …

Petit problème à l’horizon

Alors que Damien et moi sommes en plein milieu du projet, un problème vient nous frapper comme ça sans prévenir. J’utilise un WebBrowser pour me connecter à Linked In et malheureusement, il n’y a pas de WebBrowser sur la Surface. Mais nous avons une piste, il semblerait que des étudiants ont développés une application l’année  passée qui permettait d’aller sur Facebook avec la Surface donc je pense que ce n’est pas impossible. À nous de découvrir comment ils ont fait et si ça peut nous aider à avancer.

MEF .NET 3.5

Je viens d’avoir un petit problème concernant le MEF, j’utilisais le Framework 4.0 pour mon projet mais Damien m’a fait remarquer que les projets sur la surface ne pouvaient pas utiliser le Framework 4.0 mais au maximum la version 3.5. Après avoir demandé conseil à Pierre qui m’a orienté sur une ancienne preview du mef, j’ai modifié les propriétés de mon projet pour passer en 3.5 et j’ai téléchargé cette preview : source.

J’ai donc référencé la dll « System.ComponentModel.Composition » à mon projet et à mon plugin (j’ai également modifié la copie locale en true pour ne plus avoir de problème avec cette dll).

Sans oublier les using qui vont avec :

using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition;

Et voila le projet se lance comme avant! Nickel!

API LinkedIn

Je viens de recevoir ma clé API Linked In donc je commence à découvrir cette nouvelle partie. Apparament,  il est possible d’utiliser une bibliothèque OAuth pour se connecter à son compte en toute sécurité ainsi que préserver l’intimité des membres. J’ai lu que la doc n’était pas optimale mais je vais essayer de me débrouiller avec le forum.

Premier programme avec CUDA

Après avoir installé les derniers drivers Nvidia, le SDK ainsi que le Toolkit cuda, je me lance dans la doc. Il y a un Programming Guide chez Nvidia qui aide un peu mais à vrai dire j’étais vraiment dans le flou au début. Je dois avouer que j’y suis toujours un peu mais je pense avoir assimilé les principes de CUDA.

 

En fait en CUDA, l’host c’est le CPU, il demande au device (GPU) d’effectuer les calcul et le kernel c’est une portion parallèle de code à exécuter sur le device. La grille est constituée de blocs et chaque bloc est constitué de threads. Un bloc est un élément de calcul, dissociable d’autres blocs. Ils ne doivent donc pas être exécutés dans un certain ordre. Ils peuvent être exécuté  parallèlement, consécutivement ou même d’une autre manière. C’est pourquoi les threads ne peuvent communiquer qu’avec des threads du même bloc.

Dans ce programme, j’ai codé une addition matricielle, ça n’a pas l’air bien méchant mais c’était pas super simple. Dans un premier temps, il faut allouer la mémoire de l’host et du device :

int N = 1000;
size_t size = N * sizeof(float);

 // Allocation de la mémoire de l'host
 h_A = (float*)malloc(size);
 if (h_A == 0) Cleanup();
 h_B = (float*)malloc(size);
 if (h_B == 0) Cleanup();
 h_C = (float*)malloc(size);
 if (h_C == 0) Cleanup();

 Random(h_A, N);  //fonction simple qui remplit les tableaux A et B par des valeurs aléatoires (coté CPU)
 Random(h_B, N);

 // Allocation de la mémoire du device
 cutilSafeCall( cudaMalloc((void**)&d_A, size) );
 cutilSafeCall( cudaMalloc((void**)&d_B, size) );
 cutilSafeCall( cudaMalloc((void**)&d_C, size) );

Il faut maintenant envoyer les données de l’host au device pour qu’il puisse effectuer les calculs et on appelle le kernel (fonctionne comme une fonction effectuée sur le device) :

// Envoi des données de l'host au device
 cutilSafeCall( cudaMemcpy(d_A, h_A, size, cudaMemcpyHostToDevice) );
 cutilSafeCall( cudaMemcpy(d_B, h_B, size, cudaMemcpyHostToDevice) );

 // kernel
 int threadsPerBlock = 256;
 int blocksPerGrid = (N + threadsPerBlock - 1) / threadsPerBlock;
 VecAdd<<<blocksPerGrid, threadsPerBlock>>>(d_A, d_B, d_C, N); // appel du kernel

Voici le kernel (qui se trouve en dehors du main) :

// Code sur le device
__global__ void VecAdd(const float* A, const float* B, float* C, int N)
{
 int i = blockDim.x * blockIdx.x + threadIdx.x;
 if (i < N)
 {
 C[i] = A[i] + B[i];
 }
}

Et enfin on copie le tableau C du device vers l’host pour récupérer le résultat du traitement:

cutilSafeCall( cudaMemcpy(h_C, d_C, size, cudaMemcpyDeviceToHost) );

Encore une fois il est important de ne pas oublier de libérer la mémoire à la fin du programme, en utilisant une fonction Cleanup() par exemple :

void Cleanup(void)
{
 if (d_A)
 cudaFree(d_A);
 if (d_B)
 cudaFree(d_B);
 if (d_C)
 cudaFree(d_C);

 if (h_A)
 free(h_A);
 if (h_B)
 free(h_B);
 if (h_C)
 free(h_C);
}

Et voila un premier programme en C for CUDA qui marche plutôt bien!

Allocation dynamique de la mémoire en c++

Pour me préparer à la programmation parallèle, je me suis familiarisé avec l’allocation dynamique de la mémoire. En effet j’ai codé une fonction qui reçoit 3 tableaux de  200 000 éléments, d’effectuer un calcul qui permet de trouver la valeur du pixel en niveau de gris, et de renvoyer un tableau qui contient les résultats.

Voici la fonction que je viens de décrire :

int * traitement(int * rouge, int * vert, int * bleu, int nbr)
{
	int *gris = new int[nbr];

	if(gris != NULL)
	{
		int j =0;
		for(j; j < nbr ; j++)
                {
			gris[j] = (rouge[j] * 0.299) + (bleu[j] * 0.114) + (vert[j] * 0.587);
                }
	}
	return gris;
}

Dans le main, les 4 tableaux sont également déclarés dynamiquement pour pouvoir être utilisés par la fonction. Les voici :

int const nbr_pixel = 200000;
int *pixel_rouge = new int[nbr_pixel];
int *pixel_vert = new int[nbr_pixel];
int *pixel_bleu = new int[nbr_pixel];
int *pixel_gris =  new int[nbr_pixel];

L’appel de la fonction s’effectue tout simplement :

pixel_gris = traitement(pixel_rouge,pixel_vert,pixel_bleu,nbr_pixel);

Attention il est très important de libérer la mémoire à la fin de l’exécution!

delete[] pixel_rouge;
delete[] pixel_vert;
delete[] pixel_bleu;
delete[] pixel_gris;

Voilà c’était pas si compliqué que ça en fait …