IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

OpenCL Discussion :

Problème semaphore openCL


Sujet :

OpenCL

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 107
    Points : 54
    Points
    54
    Par défaut Problème semaphore openCL
    Bonjour,

    J'ai un problème en utilisant un semaphor pour bloquer l'accès à un tableau pour chaque work-item, voici le code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    __kernel void ker(__global float* v, __global int* semaphor)
    {
         int g = get_global_id(0);
     
        // wait for reource are available
         while (atom_xchg (semaphor, 1) != 0)  {}
     
     
       // utilisation de la resource pendant qu'elle est bloquée
        v[g] = g;
     
       // deblocag de la resource
       atom_xchg (semaphor, 0);
     
     
     
       return;
    }

    Lorsque je lance la fonction ça plante et je ne comprends pas pourquoi, si quelqu'un a un idée, merci. Y a t-il un autre moyen de bloquer cette ressource ? Merci

    Algernon

  2. #2
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 617
    Points
    15 617
    Par défaut

    Tu as vérifié l'extension et ajouté le pragma je suppose ?

    Sinon, je sais pas très bien ce que tu veux faire, mais ça me parait bizarre. Tu vas avoir un gros problème d'instruction divergence, c'est à dire que tous tes threads vont travailler les uns après les autres (j'ai même l'impression que ça bloquera après que le premier thread bloque la ressource, il ne pourra pas passer aux instructions suivantes, puisqu'il doit attendre que les autres threads avancent aussi et qu'ils sont bloqués)
    En général, il faut éviter les branchements (if, while) et utiliser plutôt une barrière. C'est pas pour rien qu'il n'y a pas de sémaphore en opencl
    Un peu de lecture : http://arxiv.org/pdf/1110.4623v1.pdf

    Tu veux faire quoi exactement ?

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 107
    Points : 54
    Points
    54
    Par défaut re
    Bonjour et merci,

    Ce que je veux faire c'est modifier une valeur dans mon tableau donc forcement un seul thread doit pouvoir y accéder en même temps mais lorsqu'un thread a fini de modifier mon tableau, il fait un ReleaseSemaphotre pour autoriser les threads en attente à modifier le tableau.

    Je vais regarder le lien merci

    Algernon

  4. #4
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 617
    Points
    15 617
    Par défaut
    ça je me doute que c'est pour modifier une valeur dans un tableau
    La question est surtout est ce que tu peux découper ton algo en sous algo sans accès concurrent ? Par exemple, pour faire une moyenne des éléments d'un tableau, on va faire une réduction progressive en divisant pas 2 la taille du tableau avec une barrière à chaque fois. D'où plus de problème d'accès concurrent, ni de cache, ni d'instruction divergence...
    Si tes indices de tableau sont déterministes, tu devrais pouvoir le faire

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 107
    Points : 54
    Points
    54
    Par défaut
    Merci pour la réponse, mais je ne sais pas ce que tu veux dire par barrière, et en fait j'ai simplifier l'algo que j'ai posetree en fait il s'agit de trier un tableau au fur et à mesure que un nouveau thread veut mettre une nouvelle valeur dans le tableau. Donc Je ne peux pas simplifier encore, il faut qu'un seul thread insert l'lement correctement donc besoin de bloquer les autres le temps qu'il sache ou inserer l'élément dans le tablea, faire glisser les éléménet suivants du tableau.

    Algernon

  6. #6
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 617
    Points
    15 617
    Par défaut
    ok
    Tu comprends bien que du coup, tes tâches sont sérialisées et que tu perds l'intérêt du parallélisme ?
    Barrière = http://www.khronos.org/registry/cl/s...l/barrier.html

    Tu essaies d'implémenter un algo de trie en particulier ou tu veux juste implémenter un algo de trie ?
    Les algo de trie les plus performant en mono thread ne sont pas les plus performant en multi htread

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 107
    Points : 54
    Points
    54
    Par défaut
    oui j'ai bien compris que je perds la notion de parallelisme (uniquement pour la mise à jour des valeurs du tableau), mais le rest de l'algo se fait en parallèle. Je vais regarder le lien merci.

    Algernon

    P.S. je te tiens au courant

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 107
    Points : 54
    Points
    54
    Par défaut ca ne marche toujours pas !!!
    Bonjour,

    j'ai essayé de suivre les instructions à la lettre du lien précédent mais ça crash toujours.

    Je poste le code de mon kernel en entier

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
     
    #pragma OPENCL EXTENSION cl_khr_int32_base_atomics : enable
     
    #define LOCK(a)  atom_cmpxchg (a, 0, 1)
    #define UNLOCK(a)  atom_xchg    (a, 0)
     
    /* Return the distance between the two given points
    * param a: Pointer to a constant address memory of the first point
    * param b: Pointer to a constant address memory of the second point
    * param dim: Dimension of points
    */
    float sqrtDistance (__global float* a, __global float* b, const int dim)
    {
    	float dist = 0.0f;
     
    	for (int i = 0; i < dim; ++i)
    		dist += ((a[i] - b[i]) * (a[i] - b[i]));
     
    	return sqrt (dist);
    }
     
    /*
    * Get the semaphor to lock resources for the current work-item
    * param semaphor: The semaphor used to lock resources
    */
    void GetSemaphor (__global long* semaphor)
    {
    	// Try to write 1 in the location pointed by the semaphor and reads its current content which is stored in "occupied"
    	// If the value is 0, the function may proceed because the resource is available
    	while (LOCK (semaphor));
    }
     
    /*
    * Release the semaphor in order to allow another work-item to use the resource
    * param semaphor: The semaphor used to lock resources
    */
    void ReleaseSemaphor (__global long* semaphor)
    {
    	UNLOCK (semaphor);
    }
     
    /* Return the nearest neighbor of the query point
    * param vertices: Vertices coordinates among which to search the nearest neighbors (__constant to allow all work-items to read only)
    * param queries: Array containing the query points coordinates
    * param nearest: Array containing the nearest neighbor, (__global to allow all work-items to read/write it)
    * param nearestDist: Array containing the nearest distances, (__global to allow all work-items to read/write it)
    * param k: Number of nearest neighbors required
    * param nbVertices: Number of vertices in the cloud
    * param dim: Dimension of points
    * param semaphor: Semaphor in order to update the array of distance and nearest neighbors
    */
    __kernel void nearestNeighbor (__global float* vertices,
    							   __global float* queries,
    							   __global int* nearest,
    							   __global float* nearestDist,
    							   __global const int* k,
    							   __global const int* nbVertices,
    							   __global const int* dim,
    							   __global long* semaphor)
    {
    	__private int verticesIdx = get_global_id (0);
     
    	if (verticesIdx >= *nbVertices)
    		return;		
     
    	__global float* ptrCurrentVertex = vertices + (*dim * verticesIdx);
    	float distanceVertexToQuery = sqrtDistance (ptrCurrentVertex, queries, *dim);
     
    	if (distanceVertexToQuery >= nearestDist[*k - 1])
    		return;	
     
    	// Need to compare the distance computed with the maximum distance
    	while (LOCK (semaphor));
     
    	// If the distance from the current vertex is lower than the greater distance stored in the array of k distances
    	if (distanceVertexToQuery < nearestDist[*k - 1])
    	{
    		for (int i = *k - 2; i >= -1; --i) // Search the position where to insert the new distance: distanceVertexToQuery
    		{
    			if ((i == -1) || (distanceVertexToQuery >= nearestDist[i]))
    			{
    				for (int j = *k - 1; j > i + 1; --j)
    				{
    					nearestDist[j] = nearestDist[j - 1];
    					nearest[j] = nearest[j - 1];
    				}
    				nearestDist[i + 1] = distanceVertexToQuery;
    				nearest[i + 1] = verticesIdx;
    				break;
    			}
    		}
    	}
     
    	UNLOCK (semaphor);
    	//ReleaseSemaphor (semaphor); // release the resources, so another work-item can grab it and start working
     
    }
    je appel pour enqueueNDRange avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    	size_t localThreads = 1;
    	size_t globalThreads = 1500;
    status = clEnqueueNDRangeKernel (commandQueue,  Kernel, 1, NULL, &globalThreads, &localThreads, 0, NULL, NULL);

    Au cas où, je reprécise mon problème et ce que fait mon kernel:

    en fait j'ai 1500 points 3D et je cherche les k plus proches voisins du point queries (3 coordonnées) parmi ces 1500 points.


    Donc je calcule en parallèle les distance entre mon point queries et chacun des 1500 points et ensuite, j'ai un algo de tri pour pouvoir trier mes points les plus proches en fonction de leur distance au point requete.

    Mais je ne sais pas comment faire pour bloquer tous les threads pendant que un seul modifie mon tableau à la fois.
    La solution que j'ai mise ne fonctionne pas et la carte crash, j'ai aussi testé avec BARRIER mais même problème. Combien de local thread dois-je allouer et combien de global threads ? Car peut-être c'est la mon problème?


    Merci pour votre aide

    Algernon

  9. #9
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 617
    Points
    15 617
    Par défaut
    J'ai pas encore regardé ton code

    Un k-mean sur opencl. c'est un boulot que j'avais donné à l'un de mes stagiaires. Donc pas de problème, ça se fait Je regarderais, je dois avoir des papiers la dessus

    Pour global et local, il y a des contraintes de max, regarde clPlateform (ou clInfo je ne sais plus). Ca te donnera déjà des limites max. Ensuite, l'optimisation dépend du profiling

    Tu dis que ça crash. A la compilation ? A l'exécution ? Le code hôte ou le code opencl ? Un message d'erreur généré par le runtime opencl ?

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 107
    Points : 54
    Points
    54
    Par défaut re
    merci de s'interesser à mon problème.

    Je n'ai pas d'erreur à la compilation du kernel mais lors de son execution. Ca crash en fait: l'ecran devient noir et ensuite j'ai un message windows me diant que le pilote graphique a été recupérér car perdu.


    j'ai acquérit les informations de mon device "Nvidia Corp" et voici les
    resultat avec clGetDeviceInfo,

    avec comme paramètre:

    CL_DEVICE_MAX_COMPUTE_UNITS, il me retourne 1 seul compute unit

    CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: 1024 * 1024 * 64

    je trouve ça bizarre que il ne me sorte que un seul core pour ma carte
    nvidia.
    J'ai aussi essayer en 32 bit avec les extensions, mais bon c'et quand même
    bizarre que je ne puisse pas mettre en attente plusieurs thread et en
    laisser un seul modifier mon tableau à la fois.
    J'ai fait exactement ce que propose le pdf "OpenCL in action" sur les
    mutex, mais rien a faire, il disent que il faut que le nombre de work-item
    qui execute le kernel ne doit pas dépasser le nombre max de core dans mon device, mais apparement moi c'est 1.

    C'est vraiment bizarre

    merci

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 107
    Points : 54
    Points
    54
    Par défaut re
    concernant le nombre de work group avec CL_DEVICE_MAX_WORK_GROUP_SIZE
    il me dit 1024, mais le truc c'est que j'ai essayer un exemple vraiment simple avec uniquement 6 points 3D et un seul point requete, et ça continue de crasher quand meme.

    Algernon

  12. #12
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 617
    Points
    15 617
    Par défaut
    Tu es sur d'avoir demandé les infos de ton gpu et pas ton cpu ? CL_DEVICE_TYPE_GPU
    Tu as quoi comme carte ? Tu as afficher tous tes periphérique ? Lance le programme oclDeviceQuery du SDK pour avoir toutes infos

    Pour les erreurs, je pensais plutôt aux erreurs générées lors de la compilation des kernels

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS = 1024 * 1024 * 64
    CL_DEVICE_MAX_WORK_GROUP_SIZE = 1024 
    size_t localThreads = 1;
    size_t globalThreads = 1500;
    Ton groupe est trop gros

    Tu as fait le programme sans mutex, voir s'il tournait déjà ?

    EDIT : pourquoi nbVertices, dim et k sont des pointeurs ?
    Pourquoi toutes tes variables sont en __global ? Passe les valeurs simples par copie
    Je suppose que c'est pour travailler dans un espace à N dimensions ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    __global float* ptrCurrentVertex = vertices + (*dim * verticesIdx);
    Non, si tu travailles dans un espace N, c'est la racine Nième
    Pourquoi utiliser des pointeurs et pas des tableaux ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while (LOCK (semaphor));
    Idem qu'avant, je pense que tu bloques le gestionnaire d'instruction
    Et la suite, c'est une horreur, tu exploses le parallélisme. Autant ne pas bosser sur gpu, ça sera plus efficace
    mais bon c'et quand même
    bizarre que je ne puisse pas mettre en attente plusieurs thread et en
    laisser un seul modifier mon tableau à la fois.
    Non, c'est pas bizarre. C'est pas un cpu, un gpu est optimisé pour certaines taches, et lui faire faire autre chose, tu vas dans le mur

    Fais une recherche google "kmean + gpu"

    EDIT : tu peux donner le code complet compilable ? (avec la création et l'envoi de tes données) dans un zip, ça ira

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 107
    Points : 54
    Points
    54
    Par défaut
    Bonjour et merci

    Oui je suis sur d'avoir demander les info de mon GPU car j'invoque clGetDeviceInfo avec mon device GPU(fichier cl_util.cpp)

    Ma carte: Nvidia 610m 2Go

    Lors de la compilation des kernels (run-time) je n'ai aucune erreur de compilation, d'ailleurs je génère un fihcier au cas où il y a des erreurs de compilation du kernel.

    Je suis d'accord que mon groupe est trop gros mais dans mon programme main.cpp, j'ai essayer de mettre uniquement 6 points et plus 1500 et même problème.

    Sans mutex le programme tourne et ne crash pas.

    Concernant mes pointeur:
    vertices est un tableau contenant les coordonnée 3D de mes 6 points (anciennement 1500 pts) donc vertices compte 6 * 3 floattants.

    Je suis bien conscient que bloquer un thrad pour un GPU c'est pas bon, mais knn en GPU ça existe. Je vais cherche knn GPU. Je vous joins le code que je compile ave mingw avec "g++ -o test.exe main.cpp cl_util.cpp OpenCL32.lib"

    Merci
    Fichiers attachés Fichiers attachés

  14. #14
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 107
    Points : 54
    Points
    54
    Par défaut
    Vous verrez que dans mon kernel, j'ai simplement enlever la partie traitement de la donnée bloquée pour faire le test (c'est-à-dire la partie entre LOCK (semaphor) et UNLOCK (semaphor).

    Et pareil ça crash.

    Algernon

Discussions similaires

  1. problème de Linkage ? opencl
    Par ImmoTPA dans le forum C++
    Réponses: 8
    Dernier message: 01/06/2015, 14h28
  2. Réponses: 0
    Dernier message: 11/02/2014, 00h00
  3. Problème d'installation oracle 8.1.7 sous NT
    Par Anonymous dans le forum Installation
    Réponses: 7
    Dernier message: 02/08/2002, 14h18
  4. Problème avec la mémoire virtuelle
    Par Anonymous dans le forum CORBA
    Réponses: 13
    Dernier message: 16/04/2002, 16h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo