CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

[C#] Multi-Threading plus lent que le single-Threading

-dhev
-dhev
Niveau 31
26 juin 2020 à 11:45:45

Bonjour,

Je suis actuellement en train réaliser un projet scolaire qui consiste à décrypter des fichier qui ont été crypté à l'aide d'une clé XOR en faisant du brute force (la clé est comprise entre AAAA et ZZZZ, que des lettres de l'alphabet et tout en majuscule). Une fois tous les fichiers décrypter, on les envoies sur une plateforme java pour appliquer une analyse de fréquence pour trouver la bonne clé.

Comme je m'occupe de la partie décryptage j'ai réalisé ce petit programme :

using System;
using System.Threading;

namespace BruteForce
{
    class Program
    {
        static String Decrypt(String inputString, String key)
        {
            int j = 0;

            String outputString = "";

            int len = inputString.Length;

            for (int i = 0; i < len; i++)
            {
                if (j == 4)
                {
                    j = 0;
                }

                outputString = outputString + char.ToString((char)(inputString[i] ^ key[j]));

                j = j + 1;

            }
            return outputString;
        }

        static void decrypt1()
        {
            string text2 = System.IO.File.ReadAllText(@"C:\Users\Dhev\Desktop\test\test2.txt");

            for (Char c1 = 'A'; c1 <= 'Z'; c1++)
            {
                for (Char c2 = 'A'; c2 <= 'Z'; c2++)
                {
                    for (Char c3 = 'A'; c3 <= 'Z'; c3++)
                    {
                        for (Char c4 = 'A'; c4 <= 'Z'; c4++)
                        {
                            Decrypt(text2, "" + c1 + c2 + c3 + c4);
                            
                            if ("" + c1 + c2 + c3 + c4 == "UFVX")
                            {
                                Console.WriteLine("Thread 2 finished at : " + DateTime.Now);
                                Console.WriteLine(Decrypt(text2, "" + c1 + c2 + c3 + c4));
                            }
                        }
                    }
                }
            }
        }

        public static void Main(String[] args)
        {
            Console.WriteLine("Started at : " + DateTime.Now);

            Thread t = new Thread(new ThreadStart(decrypt1));

            t.Start();


            string text = System.IO.File.ReadAllText(@"C:\Users\Dhev\Desktop\test\test.txt");
            
            for (Char c1 = 'A'; c1 <= 'Z'; c1++)
            {
                for (Char c2 = 'A'; c2 <= 'Z'; c2++)
                {
                    for (Char c3 = 'A'; c3 <= 'Z'; c3++)
                    {
                        for (Char c4 = 'A'; c4 <= 'Z'; c4++)
                        {
                            Decrypt(text, "" + c1 + c2 + c3 + c4);

                            if ("" + c1 + c2 + c3 + c4 == "ZZZZ")
                            {
                                Console.WriteLine("Thread 1 finished at : " + DateTime.Now);
                                Console.WriteLine(Decrypt(text, "" + c1 + c2 + c3 + c4));
                            }
                        }
                    }
                }
            }
        }
    }
}

j'ai réalisé 2 threads, le main et le thread " t '" qui éxecute la fonction decrypt1(). Le Multi-Threading fonctionne bien mais les résultats sont moins bon qu'en Single-Threading.

Pour info je pense pas être bottleneck par les composants de mon PC, je possède un ss2 M2 (environ 3400 Mo/s en lecture et 2300 Mo/s en ecriture) ainsi qu'un ryzen 5 3600x (6 cœurs, 12 threads).

Je voudrais savoir si c'est normal que ça soit plus lent, peut être mon code qui n'est pas assez optimisé ...

Merci d'avance, hésité pas à poser des questions si j'ai pas été clair :hap:

boucif
boucif
Niveau 24
26 juin 2020 à 17:59:24

En faisant ça tu lances juste ta tache dans un second thread,mais celui-ci sera lancé que dans un seul thread (ton appli sera certe multithread mais pas ta fonction decrypt1), tu as le mot clé parrallel ou tu peux t'amuser à gérer le nombre de thread, sinon t'as d'autre classe et d'autre outils, je pourrais pas tous te les énumérer, j'ai essayé le parrallel.for, il y a pas un gros impact dans ton cas.

Et tu es sur de ton code dans la fonction decrypt ?

Je pense qu'il y a moyen d'améliorer mon code

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Decrypt
{
    class Program
    {

        static string file = @"C:\Users\Eddy\Documents\test.txt";
        static char[] alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();

        public static void Main(String[] args)
        {
            Console.WriteLine("Started at : " + DateTime.Now);
            //Thread t = new Thread(new ThreadStart(ParrallelDecrypt));
            //t.Start();
            NormalDecrypt();
            ParrallelDecrypt();

            Console.ReadKey();
        }



        static String Decrypt(String inputString, String key)
        {
            int j = 0;

            String outputString = "";

            int len = inputString.Length;

            for (int i = 0; i < len; i++)
            {
                if (j == 4)
                {
                    j = 0;
                }

                outputString = outputString + char.ToString((char)(inputString[i] ^ key[j]));

                j = j + 1;

            }
            return outputString;
        }

        static void NormalDecrypt()
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            string text = System.IO.File.ReadAllText(file);

            for (int c1 = 0; c1 < alpha.Length; c1++)
            {
                for (int c2 = 0; c2 < alpha.Length; c2++)
                {
                    for (int c3 = 0; c3 < alpha.Length; c3++)
                    {
                        for (int c4 = 0; c4 < alpha.Length; c4++)
                        {
                            string val = String.Concat(alpha[c1], alpha[c2], alpha[c3], alpha[c4]);                                  
                            Decrypt(text, val);
                        }
                    }
                }
            }

            Console.WriteLine("Normal task finished at : " + sw.ElapsedMilliseconds);
        }

        static void ParrallelDecrypt()
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            string text = System.IO.File.ReadAllText(file);


            Parallel.For(0, alpha.Length, (c1) =>
                {

                    for (int c2 = 0; c2 < alpha.Length; c2++)
                    {
                        for (int c3 = 0; c3 < alpha.Length; c3++)
                        {
                            for (int c4 = 0; c4 < alpha.Length; c4++)
                            {
                                string val = String.Concat(alpha[c1], alpha[c2], alpha[c3], alpha[c4]);
                                Decrypt(text, val);
                                // Decrypt(text, $"{alpha[c1]}{alpha[c2]}{alpha[c3]}{alpha[c4]}");
                            }
                        }
                    }
                    //Parallel.For(0, alpha.Length, (c2) =>
                    //{
                    //    Parallel.For(0, alpha.Length, (c3) =>
                    //    {
                    //        Parallel.For(0, alpha.Length, (c4) =>
                    //        {
                    //            Decrypt(text2, "" + alpha[c1] + alpha[c2] + alpha[c3] + alpha[c4]);
                    //        });
                    //    });
                    //});
                });

            Console.WriteLine("Parrallel task finished at : " + sw.ElapsedMilliseconds);
        }

    }
}
godrik
godrik
Niveau 30
26 juin 2020 à 18:01:30

Il y a plein de raison qui peuvent faire que le code parallel est plus lent que le code sequentiel.

Ici, il y a un probleme algorithmique clair. Les deux threads font le meme calcul, les deux traversent de A a Z pour C1, c2, c3, et c4. Du fait, tu fais le travail en double. Ce que tu voudrais c'est partitioner l'espace a quatre dimensions de tes boucles. Par exemple, le premier thread fait c1 de A a M, et le deuxieme fait de N a Z.

Aussi, les deux threads lisent le fichier. Ce qui cause une augmentation du nombre d'IO.

En pratique, tu ne veux probablement pas faire le partitionement a la main. C# a certainement les fonctionalites pour faire des boucles paralleles.

En googlant: https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-write-a-simple-parallel-for-loop

boucif
boucif
Niveau 24
26 juin 2020 à 18:11:21

Le 26 juin 2020 à 18:01:30 godrik a écrit :
Il y a plein de raison qui peuvent faire que le code parallel est plus lent que le code sequentiel.

Ici, il y a un probleme algorithmique clair. Les deux threads font le meme calcul, les deux traversent de A a Z pour C1, c2, c3, et c4. Du fait, tu fais le travail en double. Ce que tu voudrais c'est partitioner l'espace a quatre dimensions de tes boucles. Par exemple, le premier thread fait c1 de A a M, et le deuxieme fait de N a Z.

Aussi, les deux threads lisent le fichier. Ce qui cause une augmentation du nombre d'IO.

En pratique, tu ne veux probablement pas faire le partitionement a la main. C# a certainement les fonctionalites pour faire des boucles paralleles.

En googlant: https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-write-a-simple-parallel-for-loop

Non le fichier est lu qu'une seule fois normalement, enfin deux fois il fait deux filereadalltext, en tout cas la vitesse de son SSD aura que très peu d'impact sur sa fonction (à part si son fichier fait plusieur centaine de Mo).

Pour ton utilisation de j dans ton decrypt tu es sur que c'est bien ça que tu voulais faire.

godrik
godrik
Niveau 30
26 juin 2020 à 18:39:50

Non le fichier est lu qu'une seule fois normalement, enfin deux fois il fait deux filereadalltext, en tout cas la vitesse de son SSD aura que très peu d'impact sur sa fonction (à part si son fichier fait plusieur centaine de Mo).

Certainement, mais c'est toujours bon de rappeller les bases aux gens.

Tu n'imagines pas le nombre de gens qui viennent me voir pour rendre leur codes paralleles et une fois que tu as retire toutes les idioties qui sont dans le code et corriger l'algorithmique du probleme avec des techniques de base, les questions de performances ont disparue.

NeuroShitical
NeuroShitical
Niveau 9
27 juin 2020 à 10:11:25

J'allais te conseiller d'utiliser OpenMp pour paralleliser tout ça mais C# je sais pas si c'est dispo :(
Si tu te sens à l'aise avec le C tu peux switcher, c'est un outil très puissant

boucif
boucif
Niveau 24
27 juin 2020 à 10:29:39

Le c# intègre de base ce genre d’outils pas besoin de bibliothèque externe

godrik
godrik
Niveau 30
27 juin 2020 à 17:27:50

Le 27 juin 2020 à 10:11:25 NeuroShitical a écrit :
J'allais te conseiller d'utiliser OpenMp pour paralleliser tout ça mais C# je sais pas si c'est dispo :(
Si tu te sens à l'aise avec le C tu peux switcher, c'est un outil très puissant

OpenMP n'est disponible qu'en C, C++, et FORTRAN. Les languages plus recent ont typiquement ete construit avec parallel-for dans leur lib standard.

Sous forums
  • Aide à l'achat Mac
  • Steam Deck
  • Création de sites web
  • Création de Jeux
  • Linux
  • Programmation
  • Internet
  • Macintosh
  • Hardware
La vidéo du moment