scénario: strong> p>
Étant donné un ensemble de ressources R:
donné un ensemble de threads t, qui fonctionnera en parallèle:
Chaque fil doit accéder à une liste de N ressources. Chaque liste est un échantillon de R, ce qui signifie que chaque ressource est unique dans chaque liste:
Mais puisque les listes d'accès sont échantillonnées au hasard, il peut y avoir des conflits:
Les listes de ressources aléatoires seront initialisées une fois au début. Après cela, chaque thread fera une opération atomicadd sur chaque ressource de la liste, par la suite. L'ordre d'accès des ressources dans chaque liste est hors de propos. P>
Y a-t-il un algorithme qui trie les listes de planification afin que le nombre de conflits d'écriture soit minimisé? Donc, le résultat final ressemblerait à ceci:
Je cherche une solution analytique à ce problème. Pourrait-il être NP-complet? Si tel est le cas, je pense à concevoir un algorithme génétique pour résoudre ce problème. P>
EDIT 1 STROR>: Diagrammes ajoutés. P> p>
p>
p>
p>
p>
4 Réponses :
compteurResourcelist code> qui stocke le code> ordre décroissant des comptes. Cela prendra l'heure O (RT * Log (RT)). Le pourquoi? Em> de cela est expliqué dans l'échantillon exécuté ci-dessous. Également dans la même itération, nous créons un haschmap afin que nous puissions trouver dans O (1) de temps sur lequel la liste des threads de cet ID de ressource doit être placée (en fonction de l'idée de Index inversé pour ceux qui peuvent raconter). LI>
- Ensuite, nous créons une matrice - appelée
tritedlistMatrix code> - de t lignes et r colonnes. Dans cette matrice, nous commençons par placer les identifiants de ressources à partir de compteurResourcelist code> dans la ligne de threads qui contenait initialement cet ID de ressource maximum survenant. De cette façon, les ID de ressources échappent dans l'ordre de la plupart se produisant au moins se produisant em>. Li>
- Pour aider à l'insertion des ressources ressources, nous créons également un
int [t] freecolumncount code> qui empêche le nombre de colonnes totales gratuites pour chaque thread. Étant donné que le thread avec des emplacements gratuits moindes a moins de capacité à déplacer l'ID de ressource en cas d'un conflit, une pièce d'identité de ressources sera d'abord remplie dans la ligne qui contient des emplacements maux pour les fils contenant cet identifiant de ressources. li>
- à partir de la colonne de la 0ème colonne du premier fil contenant l'ID de ressource survenant le plus élevé, nous choisissons l'emplacement de l'identifiant suivant à mettre à l'aide des formules
rangées = getRowforresource (ID) dans le hashmap et la colonne = ( Colonne + 1)% R code>. Si la colonne résultante d'une rangée est occupée, nous prenons la prochaine valeur de colonne inoccupée en itérant à l'aide de la même formule de la valeur de colonne, sans changer la ligne. Par conséquent - Les colonnes sont soumises à une enveloppe et les lignes sont déterminées à partir du hashmap de manière à ce qu'un ID de ressource passe dans la liste correcte et à la localisation la moins conflictuelle forte>. Li>.
- Une fois cette matrice complètement peuplée, commencez par une rangée de la section 0 et attribuez les lignes à chaque fil comme leur nouvelle liste de ressources em>. li>.
ol>
ATTN: strong> J'ai mentionné par intermittence la complexité de quelques étapes, mais mettra à jour avec la complexité globale du temps d'exécution. Pour le moment, j'essaie de trouver un algorithme correct. P> un échantillon exécuté h2>
hypothèses et définitions initiales: p>
- Nombre de threads =
t fort>, à partir du fil 0 au t-1 li>
- Nombre de ressources pour chaque thread =
r strong> li>
- Total des ressources pour préparer la liste des ressources pour les threads sera
> = r strong> li>
ul> Commençons par un cas de T = 4. T0 = {4, 3, 5}, T1 = {1, 2, 6}, T2 = {3, 1, 2}, T4 = { 2, 7, 1}. Maintenant, je sais que cette liste n'a pas déjà de conflit. Il devrait y avoir une étape de prétraitement qui découvre s'il devrait y avoir un re-arrangement effectué en premier lieu. Comme si les listes ont déjà le minimum de conflits possibles ou s'il n'y a pas de conflit, les listes doivent être renvoyées comme elles sont. Néanmoins, voyons le pseudocode en action. P>
Nous lisons d'abord toutes les ressources dans toutes les listes et mettons-les dans des godets individuels d'ID de ressources. Utilisation de compter le tri , ce sera une étape linéaire prise O (tr + constante ) fort> temps. Cependant, comme cela va simplement donner un compte d'identité de ressources, nous devrons utiliser davantage Fusionner le tri trier les identifiants dans l'ordre de décroissance. Cette étape prendra O ((RT) Journal (RT)) Strong>. Le résultat sera une liste ou des identifiants triés dans l'ordre décroissant d'occurrence - P>
compteurResourcelist code> = , , ,
blockQuote> Au cours de la même itération, nous créons également le tableau HASHMAP et le tableau code> freecolumncount CODE>. P>
Suivant, nous créons le sortidlistMatrix code> qui est peuplé à partir de rangée = premier thread à contenir de la ressource-id maximum survenant em> (en appelant getRowforresource (ID)) em> strong>, colonne = 0 em>. La matrice sera initialement vide puis renseignée comme suit: P> Initially:
{_, _, _}
{_, _, _}
{_, _, _}
{_, _, _}
Taking 1st element '1' at (1, 0):
{_, _, _}
{1, _, _}
{_, _, _}
{_, _, _}
Taking 2nd element '1' at (2, 1):
{_, _, _}
{1, _, _}
{_, 1, _}
{_, _, _}
Taking 3rd element '1' at (3, 2):
{_, _, _}
{1, _, _}
{_, 1, _}
{_, _, 1}
Taking 4th element '2' at (1, 1) as (1, 0) is already occupied:
{_, _, _}
{1, 2, _}
{_, 1, _}
{_, _, 1}
Taking 5th element '2' at (2, 2):
{_, _, _}
{1, 2, _}
{_, 1, 2}
{_, _, 1}
Taking 6th element '2' at (3, 0):
{_, _, _}
{1, 2, _}
{_, 1, 2}
{2, _, 1}
Taking 7th element '3' at (0, 0) because row 2 has least free slots:
{_, _, _}
{1, 2, _}
{3, 1, 2}
{2, _, 1}
Taking 8th element '3' at (0, 1):
{_, 3, _}
{1, 2, _}
{3, 1, 2}
{2, _, 1}
Taking 9th element '4' at (0, 2):
{_, 3, 4}
{1, 2, _}
{3, 1, 2}
{2, _, 1}
Taking 10th element '5' at (0, 0):
{5, 3, 4}
{1, 2, _}
{3, 1, 2}
{2, _, 1}
Taking 11th element '6' at (1, 2):
{5, 3, 4}
{1, 2, 6}
{3, 1, 2}
{2, _, 1}
Taking 12th element '7' at (3, 1):
{5, 3, 4}
{1, 2, 6}
{3, 1, 2}
{2, 7, 1}
Je pense que la question est de demander Je pense qu'une solution optimale est la NP complète, mais je rechercherais le nombre de surveurs dans l'ensemble pour chaque ressource. P>
La ressource la plus couramment utilisée est la plus difficile à planifier. Ainsi, je placerais dans chacun des threads cette ressource en position 1, 2, 3, 4, ... jusqu'à ce que le conflit se produise (ce qui peut être inévitable) par exemple. 1,2,3,4, ..., n, 1, 2, .... p>
Ce sont les "grosses pierres". Ceux-ci doivent être placés en premier. P>
La ressource suivante la plus couramment utilisée devrait alors être essayée. Cela devrait identifier les machines à sous (1 => N) ont été utilisées récemment et recherchées à travers cette liste pour une tranche à la fois non allouée et non utilisée récemment. p>
Quelle que soit la fente choisie, il se déplace vers le haut de la file d'attente récemment utilisée à éviter pendant un moment. P>
Ceci favorise la distribution de la ressource, mais permet des doublons. Ces doublons deviendront récemment utilisés et non favorisés pour la planification jusqu'à ce qu'aucun choix valide ne soit disponible. P>
L'étape 2 est répétée pour chacune des ressources dans l'ordre de leurs occurrences. P> Étape 1 H2>
Étape 2 H2>
Enfin h2>
Ok .. donc j'ai senti que votre réponse était la plus optimale et je suis même enlevée votre réponse. Je viens de réaliser que pour la liste des ressources de {1, 2, 3} donnée à 4 threads, votre solution est au moins pire que ma solution. Mentionner cela pour attirer votre attention sur le cas.
Si vous avez moins de ressources que des threads, la commande n'a pas beaucoup d'importance. Je m'attendrais à ce que la ressource la plus couramment utilisée soit programmée {1, x, x}, {x, 1, x}, {x, x, 1}, {1, x, x}. Puis la ressource suivante {1, 2, x}, {2, 1, x}, {2, x, 1}, {1, x, 2} enfin {1,2,3}, {2,1,3 }, {2,3,1}, {1,3,2}
La tâche est de fournir l'ordre le moins conflictuel. Donc, la commande est-elle importante, non? :) Surtout quand il existe une commande qui est i> avoir un conflit moindre que la solution provenant de votre algorithme. Si même pour un cas, la solution n'est pas correcte, l'algorithme est fausse.
Au début, il ressemble à une variante de OSPSP . Nous devons planifier des ressources Cependant, nous devons remplir la séquence entière dans Donc, nous recherchons la planification dans où construisons un graphique Chaque filet Vertex a un degré de Notre objectif est de colorer ce graphique avec pas de fil vertex n'a deux bords adjacents avec la même couleur p> li>
Nombre de bords adjacents de la même couleur est minimal p> li>
ul>
S'il n'y a pas de vertex de ressource avec degré Colorage de bord graphique bipartite peut être effectué dans Maintenant, supposons que nous ayons un sommet de ressource avec degré Nous avons des verxes Il ne peut pas être moins important, car chaque couleur conflictuelle dans la coloration de bord est un conflit dans notre calendrier et pour chaque sommet avec degré Maintenant, nous voulons construire une solution avec exactement Insérez maintenant les bords précédemment supprimés Ce pas entier avec des conflits peut être fait dans: p>
Une solution si complète peut être réalisée dans r code> sur
t code> processeurs. Certains temps de planification sont
0 code>, certains sont
1 code>. P>
N code> TIMESTPS, et il existe exactement
N * t code> temps de planification non nul. P>
n code> heure, sans
TT code> (car aucun thread ne peut fonctionner sur deux ressources en même temps), et avec minimum Nombre de
RR code> Conflits. Je suppose que la fonction cible à minimiser est la suivante: p>
compte code> est un certain nombre de threads à l'aide de ressources
j code> à l'heure
i code>. p>
Construire un graphe de problème h2>
g = (v, e) code> avec sommet pour chaque thread (première partie) et chaque ressource (deuxième partie). Pour chaque heure de planification non nulle, nous avons un bord du fil à la ressource. Ce graphique est évidemment bipartite. P>
n code>. p>
n code> couleurs, de cette manière que: p>
Solution GRATUITE CONFLIT H2>
d> n code>, le graphique a une coloration de bord approprié avec au plus de couleurs
n code>. Et une bonne coloration est bien sûr la meilleure coloration en termes de fonction cible - il n'y a pas de conflit du tout. P>
O (n * t * R) code> temps
. P>
Solution avec conflits h2>
d> n code>. Cela signifie qu'il n'y a pas de colorant de bord approprié avec les couleurs
N code> et nous aurons un conflit dans notre horaire. P>
v_conflict code> avec degré
d> n code>. Ensuite, le nombre de conflits est exactement
q code>:
p>
d> n code> nous avons au moins
d - D - n code> couleurs en conflit. P>
q code> conflits. Supprimez tout ensemble d'arêtes de chaque sommet dans
v_conflict code> pour réduire leur degré sur
n code>. Nous avons supprimé exactement
q code> bords. Maintenant, nous avons une solution sans conflit (en tant que correction du graphique approprié en coloration dans
n code> couleurs). P>
q code>, attribuant la couleur qui n'est pas encore attribuée à un bord de leur vert de fil correspondant. Comme chaque EDGE supplémentaire ne peut introduire que 1 conflit, nous avons maintenant exactement
Q code>, qui est prouvé à la limite inférieure. P>
O (r) code> pour déterminer
v_conflict code> p> li>
O (r * t) code> pour éliminer les bords contradictoires p> li>
O (n * t * r) code> pour résoudre la version réduite sans conflit. p> li>
O (n * q) code> pour ajouter les bords retour au graphique p> li>
ul>
O (n * t * r) code> heure. P>
Je ne suis au courant d'aucun algorithme. Une approche avec la compréhension que son opk pour commander la séquence serait de - avoir des verrous qui représentent chacune de la ressource. p>
Un fil en accédant à une ressource, obtient le verrou correspondant pour cette ressource. Si un autre thread veut accéder à la même ressource, il résoudra l'accès avec le prochain. Par exemple, T1 peut accéder à R1. Si T2 nécessite également l'accès à R1, T2 peut plutôt reprogrammer l'accès (échange) pour R1 avec distinguer l'accès pour R2, puis prendre R1 supposant que T1 est effectué avec elle. P>
Quelle est la ressource? Est-ce que l'écriture vers la ressource x interfère du tout avec l'écriture sur la ressource y? Si oui, cela importe-t-il ce que X et Y (c'est-à-dire que toutes les informations relatives aux ressources interférent mutuellement)? Votre notation est difficile à comprendre. Vous dites que la matrice s a | t | rangées et | n | Les colonnes et chaque entrée sont un élément de R. SO N'est-ce pas | R |, alors, le nombre total d'éléments? Mais si c'est le cas, certaines de vos idées n'ont pas de sens. Par exemple, si | t | <= | R |, ... i>. Mais ne va pas | t | toujours être <= | r | Quand | n | > = 1? Ouais, notation déroutante.
Merci pour votre commentaire. Les éléments de la matrice S sont des indices des ressources, car les ressources sont identifiées par leur indice, je considère que l'ensemble des indices des ressources des ressources. Donc, les chiffres sont des éléments de jeu R, bien que les dimensions de cette matrice soient | T | X | N |. Je vais fournir des diagrammes, j'espère que ma notation a du sens alors. J'ai essayé de formuler le problème aussi général que possible. Je crains que si j'écris sur le contexte dans lequel j'ai besoin de cela, cela devient encore plus déroutant. Les ressources sont indépendantes, la rédaction de x n'interfère pas avec l'écriture à y.
Donc, en termes simplifiés, vous demandez s'il existe un algorithme qui minimisera les occurrences de la même ressource dans une colonne particulière. L'idéal est qu'un r ne semble pas apparaître plus d'une fois dans n'importe quelle colonne?
Exactement. Mais dès qu'il y ait plus de threads que de ressources, les conflits sont inévitables, mais le nombre de conflits pour chaque ressource peut toujours être minimisé (donc, par exemple, au lieu de 5 conflits dans une colonne, il n'y aura que 2 dans la version optimisée). .
Je ne pense pas "si | t | <= | r |, une solution sans conflit est possible." est vrai. R = {1, 2, 3, 4, 5}, n = 2, et les listes d'accès sont T1 = {1, 2}, T2 = {1, 3}, T3 = {1, 4}, T4 = { 1, 5}. Si nous reconstruisons les listes, nous pouvons aller sans conflit à l'étape 1: T1 = {1, 2}, T2 = {3, 1}, T3 = {4, 1}, T4 = {5, 1}, mais un conflit arriver à l'étape 2. Je ne peux pas penser à une solution de force non brute, mais c'est un problème intéressant.
En fait, je pense que toutes vos déclarations ne sont vraies que pour N = R (et dans l'exemple, N = 4 et R = 6).