Je profile une application C# et il ressemble à deux threads appelant chacun Dictionary<>.ContainsKey()
5000 fois chacun sur deux dictionnaires distincts mais identiques (avec seulement deux éléments) est deux fois plus lent qu'un thread appelant Dictionary<>.ContainsKey()
sur un seul dictionnaire 10000 fois.Plusieurs threads ralentissent l'accès global au dictionnaire?
Je mesure le "temps de filetage" en utilisant un outil appelé JetBrains dotTrace. J'utilise explicitement des copies des mêmes données, donc il n'y a pas de primitives de synchronisation que j'utilise. Est-il possible que .NET fasse de la synchronisation dans les coulisses?
J'ai une machine dual core, et il y a trois threads en cours d'exécution: l'un est bloqué en utilisant Semaphore.WaitAll()
tandis que le travail est effectué sur deux nouveaux threads dont la priorité est ThreadPriority.Highest
.
Des coupables évidents comme, ne pas réellement exécuter le code en parallèle, et ne pas utiliser une version release ont été exclus.
EDIT:
Les gens veulent le code. Très bien, alors:
private int ReduceArrayIteration(VM vm, HeronValue[] input, int begin, int cnt)
{
if (cnt <= 1)
return cnt;
int cur = begin;
for (int i=0; i < cnt - 1; i += 2)
{
// The next two calls are effectively dominated by a call
// to dictionary ContainsKey
vm.SetVar(a, input[begin + i]);
vm.SetVar(b, input[begin + i + 1]);
input[cur++] = vm.Eval(expr);
}
if (cnt % 2 == 1)
{
input[cur++] = input[begin + cnt - 1];
}
int r = cur - begin;
Debug.Assert(r >= 1);
Debug.Assert(r < cnt);
return r;
}
// From VM
public void SetVar(string s, HeronValue o)
{
Debug.Assert(o != null);
frames.Peek().SetVar(s, o);
}
// From Frame
public bool SetVar(string s, HeronValue o)
{
for (int i = scopes.Count; i > 0; --i)
{
// Scope is a derived class of Dictionary
Scope tbl = scopes[i - 1];
if (tbl.HasName(s))
{
tbl[s] = o;
return false;
}
}
return false;
}
Maintenant, voici le code de reproduction de fil, ce qui pourrait être retardé:
public static class WorkSplitter
{
static WaitHandle[] signals;
public static void ThreadStarter(Object o)
{
Task task = o as Task;
task.Run();
}
public static void SplitWork(List<Task> tasks)
{
signals = new WaitHandle[tasks.Count];
for (int i = 0; i < tasks.Count; ++i)
signals[i] = tasks[i].done;
for (int i = 0; i < tasks.Count; ++i)
{
Thread t = new Thread(ThreadStarter);
t.Priority = ThreadPriority.Highest;
t.Start(tasks[i]);
}
Semaphore.WaitAll(signals);
}
}
Pourriez-vous peut-être expliquer le problème que vous essayez de résoudre avec ces threads et dictionnaires ... –
Écrire un interpréteur, et j'ai besoin de paralléliser certaines opérations vectorielles. – cdiggins
Vous devriez publier votre code. – ChaosPandion