Question

Dites que j'ai une tâche liée aux entrées-sorties. J'utilise WithDegreeOfParallelism = 10 et WithExecution = ForceParallelism, mais la requête n'utilise toujours que deux threads. Pourquoi?

Je comprends que PLINQ choisira généralement un degré de parallélisme égal à mon nombre de cœurs, mais pourquoi ignore-t-il ma demande spécifique de parallélisme supérieur?

static void Main(string[] args)
{
    TestParallel(0.UpTo(8));
}

private static void TestParallel(IEnumerable<int> input)
{
    var timer = new Stopwatch();
    timer.Start();
    var size = input.Count();

    if (input.AsParallel().
        WithDegreeOfParallelism(10).
        WithExecutionMode(ParallelExecutionMode.ForceParallelism).
        Where(IsOdd).Count() != size / 2)
        throw new Exception("Failed to count the odds");

    timer.Stop();
    Console.WriteLine("Tested " + size + " numbers in " + timer.Elapsed.TotalSeconds + " seconds");
}

private static bool IsOdd(int n)
{
    Thread.Sleep(1000);
    return n%2 == 1;
}
Était-ce utile?

La solution

PLINQ essaie de trouver le nombre optimal de threads pour exécuter ce que vous voulez, aussi rapidement que possible. Si vous n'avez que 2 cœurs sur votre processeur, ce nombre est très probablement 2. Si vous avez un quad, vous Il est plus probable que 4 threads apparaissent, mais la création de 4 threads sur une machine dual core n'améliorerait pas réellement les performances, car seuls 2 threads pourraient être actifs en même temps.

En outre, avec les opérations basées sur les E / S, il est probable que des threads supplémentaires se bloqueraient simplement lors de la première opération IO effectuée.

Autres conseils

10 est le maximum

  

Définit le degré de parallélisme à utiliser   dans une requête. Le degré de parallélisme est   le nombre maximum de concurremment   l'exécution des tâches qui seront utilisées pour   traiter la requête.

À partir d'ici:

MSDN

Il semble que PLINQ syntonise le nombre de threads. Lorsque j'ai enveloppé le code ci-dessus dans une boucle while (true), les deux premières itérations ont duré deux secondes, mais la troisième et plus n'a pris qu'une seconde. PLINQ a compris que les noyaux sont inactifs et a augmenté le nombre de threads. Impressionnant!

J'accepterais Rory, sauf IO. Nous n’avons pas testé avec les E / S de disque, mais les E / S de réseau peuvent être définitivement plus efficaces avec plus de threads qu’il n’ya de cœurs sur le CPU.

Test simple (il serait plus correct d'exécuter le test avec chaque nombre de threads plusieurs fois, car la vitesse du réseau n'est pas constante, mais quand même) pour prouver que:

    [Test]
    public void TestDownloadThreadsImpactToSpeed()
    {
        var sampleImages = Enumerable.Range(0, 100)
            .Select(x => "url to some quite large file from good server which does not have anti DSS stuff.")
            .ToArray();            

        for (int i = 0; i < 8; i++)
        {
            var start = DateTime.Now;
            var threadCount = (int)Math.Pow(2, i);
            Parallel.For(0, sampleImages.Length - 1, new ParallelOptions {MaxDegreeOfParallelism = threadCount},
                         index =>
                             {
                                 using (var webClient = new WebClient())
                                 {
                                     webClient.DownloadFile(sampleImages[index],
                                                            string.Format(@"c:\test\{0}", index));
                                 }
                             });

            Console.WriteLine("Number of threads: {0}, Seconds: {1}", threadCount, (DateTime.Now - start).TotalSeconds);
        }
    }

Le résultat avec une image 500x500px de CDN utilisant une machine à 8 noyaux avec SSD était:

  

Nombre de threads: 1, Secondes: 25.3904522
  Nombre de fils: 2, Secondes: 10.8986233
  Nombre de fils: 4, Secondes: 9.9325681
  Nombre de threads: 8, Secondes: 3.7352137
  Nombre de fils: 16, Secondes: 3.3071892
  Nombre de threads: 32, Secondes: 3.1421797
  Nombre de discussions: 64, Secondes: 3.1161782
  Nombre de threads: 128, Secondes: 3,7272132

Le dernier résultat a un tel temps, je pense d’abord parce qu’il ne faut télécharger que 100 images :)

La différence de temps entre 8 et 64 fils n’est pas si grande, mais sur une machine à 8 cœurs. Si c’était une machine à 2 cœurs (ordinateur portable d’utilisateur final bon marché), je pense que le fait d’imposer l’utilisation de 8 threads aurait plus d’impact que sur une machine à 8 cœurs obligeant à utiliser 64 threads.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top