zoukankan      html  css  js  c++  java
  • 《C#并行编程高级教程》第2章 命令式编程 笔记

    Parallel.Invoke

    并行执行多个方法,只有在所有方法都执行后才会返回
    static void Main(string[] args)
    {
        Parallel.Invoke(
        () => ConvertEllipses(),
        () => ConvertRectangles(),
        () => ConvertLines(),
        () => ConvertText());
        System.Console.ReadLine();
    }
     
    static void ConvertEllipses()
    {
        System.Console.WriteLine("Ellipses converted.");
    }
     
     
    static void ConvertRectangles()
    {
        System.Console.WriteLine("Rectangles converted.");
    }
     
    static void ConvertLines()
    {
        System.Console.WriteLine("Lines converted.");
    }
     
    static void ConvertText()
    {
        System.Console.WriteLine("Text converted.");
    }
     
    先给两段基本代码,方便后面理解。
    将Byte[]转成16进制表示的字符串
    private static string ConvertToHexString(Byte[] byteArray)
    {
        // Convert the byte array to hexadecimal string
        var sb = new StringBuilder(byteArray.Length);
        for (int i = 0; i < byteArray.Length; i++)
        {
            sb.Append(byteArray[i].ToString("X2"));
        }
        return sb.ToString();
    }
    生成一些AES的Key,并计时
    AesManaged在System.Security.Cryptography
    Stopwatch和Debug在System.Diagnostics
     
    private const int NUM_MD5_HASHES = 100000;
    private static void GenerateAESKeys()
    {
        var sw = Stopwatch.StartNew();
        var aesM = new AesManaged();
        for (int i = 1; i <= NUM_AES_KEYS; i++)
        {
            aesM.GenerateKey();
            byte[] result = aesM.Key;
            string hexString = ConvertToHexString(result);
            // Console.WriteLine("AES KEY: {0} ", hexString);
        }
        Debug.WriteLine("AES: " + sw.Elapsed.ToString());
    }
     

    Parallel.For

    不支持浮点数和进步。无法保证迭代执行的顺序
    private static void ParallelGenerateAESKeys()
    {
        var sw = Stopwatch.StartNew();
        Parallel.For(1, NUM_AES_KEYS + 1, (int i) =>
        {
            var aesM = new AesManaged();
            byte[] result = aesM.Key;
            string hexString = ConvertToHexString(result);
            // Console.WriteLine(“AES KEY: {0} “, hexString);
        });
        Debug.WriteLine("AES: " + sw.Elapsed.ToString());
    }

    Parallel.ForEach

    利用一个范围整数作为一组数据,通过一个分区器,把数据分成一组数据块。每一块的数据都通过循环的方式处理,而这些循环都是并行的。
    private static void ParallelPartitionGenerateAESKeys()
    {
        var sw = Stopwatch.StartNew();
        Parallel.ForEach(Partitioner.Create(1, NUM_AES_KEYS + 1), range =>
        {
            var aesM = new AesManaged();
            Debug.WriteLine(
                "AES Range ({0}, {1}. TimeOfDay before inner loop starts: {2})",
                range.Item1, range.Item2,
                DateTime.Now.TimeOfDay);
            for (int i = range.Item1; i < range.Item2; i++)
            {
                aesM.GenerateKey();
                byte[] result = aesM.Key;
                string hexString = ConvertToHexString(result);
                // Console.WriteLine(“AES KEY: {0} “, hexString);
            }
        });
        Debug.WriteLine("AES: " + sw.Elapsed.ToString());
    }

    根据内核数目优化分区

    Parallel.ForEach(
        Partitioner.Create(1,NUM_AES_KEYS,((int)(NUM_AES_KEYS / Environment.ProcessorCount) + 1)),
        range =>
        {
            //...
        });

    使用IEnumerable数据源

    private const int NUM_MD5_HASHES = 100000;
    private static IEnumerable<int> GenerateMD5InputData()
    {
        return Enumerable.Range(1, NUM_MD5_HASHES);
    }
     
    private static void ParallelForEachGenerateMD5Hashes()
    {
        var sw = Stopwatch.StartNew();
        var inputData = GenerateMD5InputData();
        Parallel.ForEach(inputData, (int number) =>
        {
            var md5M = MD5.Create();
            byte[] data =
                Encoding.Unicode.GetBytes(
                    Environment.UserName + number.ToString());
            byte[] result = md5M.ComputeHash(data);
            string hexString = ConvertToHexString(result);
            // Console.WriteLine("MD5 HASH: {0}", hexString);
        });
        Debug.WriteLine("MD5: " + sw.Elapsed.ToString());
    }

    从并行循环中退出

    在参数中使用ParallelLoopState,就可以使用loopState.Break();或者loopState.Stop();进行退出。其中的差别在于,假设调用Break的时候正在处理迭代100,那么可以保证小于100的迭代都被执行,而Stop不保证这个。
    ParallelLoopResult作为返回值,可以知道是否是正常完成或者被Break的
    ParallelLoopResult loopResult = Parallel.ForEach(inputData,
    (int number, ParallelLoopState loopState) =>
    {
        //...
        loopState.Break();
        return;
        //...
    });

    捕获并行循环的异常

    try
    {
        loopResult = Parallel.ForEach(inputData,
        (int number, ParallelLoopState loopState) =>
        {
            //...
            throw new Exception();
            //..
        });
    }
    catch (AggregateException ex)
    {
        foreach (Exception innerEx in ex.InnerExceptions)
        {
            Debug.WriteLine(innerEx.ToString());
        }
    }

    ParaleelOption

    用于修改并行度。
    private static void ParallelGenerateAESKeysMaxDegree(int maxDegree)
    {
        var parallelOptions = new ParallelOptions();
        parallelOptions.MaxDegreeOfParallelism = maxDegree;
        var sw = Stopwatch.StartNew();
        Parallel.For(1, NUM_AES_KEYS + 1, parallelOptions, (int i) =>
        {
            var aesM = new AesManaged();
            byte[] result = aesM.Key;
            string hexString = ConvertToHexString(result);
            // Console.WriteLine(“AES KEY: {0} “, hexString);
        });
        Debug.WriteLine("AES: " + sw.Elapsed.ToString());
    }
     
     





  • 相关阅读:
    173. Binary Search Tree Iterator
    199. Binary Tree Right Side View
    230. Kth Smallest Element in a BST
    236. Lowest Common Ancestor of a Binary Tree
    337. House Robber III
    449. Serialize and Deserialize BST
    508. Most Frequent Subtree Sum
    513. Find Bottom Left Tree Value
    129. Sum Root to Leaf Numbers
    652. Find Duplicate Subtrees
  • 原文地址:https://www.cnblogs.com/atskyline/p/3234292.html
Copyright © 2011-2022 走看看