主頁 > .NET開發 > 請問在密集計算的任務中,能真正做到多執行緒“同時”運行計算么?

請問在密集計算的任務中,能真正做到多執行緒“同時”運行計算么?

2021-04-16 05:12:20 .NET開發

有個簽名的函式。因為時常要同時簽名多條資料。 假設每次簽名需要10ms時間。我一次需要簽名10條資料。順序簽名需要100ms。按理說我開10個TASK 同時簽名  按理說如果cpu資源“足夠”的情況下 TASK完成時間應該是10ms加上一點損耗。。 但是實際上 TASK完成時間有時候甚至能超過100ms(順序運行的總和時間)。。后來去查了一下資料。發現很多語言都有執行緒鎖。實際只是“并發”,而不是“并行”在計算。
為了驗證是否硬體資源問題。我嘗試用多個行程跑同樣的連續單執行緒簽名的程式。得到的結果也也似乎驗證了 執行緒只是并發運行。(多個行程下。每個行程使用的簽名時間都是10ms,當然有誤差和cpu占用的損耗)。。


所以。我想請問2個問題

1,C# 能否自身做到真正的“并行”多執行緒執行?

2,如果無法并行處理。那么我打算用多行程方式解決。那么請問為了降低兩個行程間的延遲。請問用那種多行程間通訊方式?大概查了一下。有ipc、共享記憶體等。。 。我是在.net core下用。。程式在windows下開發除錯。在linux下運行。 也就是說最好能兼容兩種系統。并且通訊延遲要越低越好。至少在毫秒內的。請問我應該著重去找哪方面的資料?

uj5u.com熱心網友回復:

這個問題承接你上一個,你說的很對
執行緒只是一種利用短暫時間片切換并發執行,造成表象上的并行手段(因為cpu運算快,而一個時間片只有幾納秒,所以感官上他是連續執行)
當然涉及到執行緒切換,所以你加入的執行緒越多,分配到每個執行緒的總執行時間就會相應延長
所以就產生的多核運算,而在netcore里,多核運算為Parallel 并行計算,他是對多核cpu支持優化,也就是盡量把你的執行緒任務分給不同的cpu,這樣他才是真正的同時執行

另外在補充一下你上個帖子的Gc影響
1.大多數討論gc對程式影響的討論,發生在程式占用大量物理記憶體,也就是兩類
 一:你程式快速產生大量1代物件,而且都在用gc不能給你釋放
 二:你的程式有嚴重的記憶體泄漏,不在gc的管控范圍

這樣如果你程式占用記憶體超過800M,而且在上面兩種情況,gc一次清理,也就只能騰出1-2m,此時在申請記憶體,就會強迫gc去清理,這樣造成頻繁gc動作,幾乎每次都要去清理,那么就會慢

這點東西,我們看我們的C盤就好,如果說剛裝機C盤剩下60G,我3個月清理一回都行,因為他足夠分,3月清理一會一次釋放個20G都成
但是如果隨著時間推進,我們裝的東西一多,就剩6-12G的時候,我就幾天清理一次都不行。基本上到那個時候,C盤都是我們必須要的,在清理都請清不出來啥,即使我天天清理,也就勉強維持在8G上下。

所以嚴格上說gc對程式有影響,但他發生在總物理記憶體占用超過90%,Gc必須每個動作都要清理一遍的情況。所以還是前面的結論,我們首先要討論的事情是為啥會存在那么多Gc清不動的東西,,對,我們對待C盤的態度一樣,如果占用超過90%,我們只能去看到底C盤裝了啥,為啥C盤有那么多,不能清,也不敢清,或者我都不知道他那里用的東西--------卸(內)載(存)遺(泄)留(漏)

uj5u.com熱心網友回復:

實際上你的問題,更多情況下我們是拆分任務

我們既然知道多執行緒切換總會消耗時間,那么我們就需要拆成很多小任務,這些小任務他可以很快走掉,走掉了。就不參與

另外一個是合理分派IO任務和計算任務。IO任務總體上不怎么消耗cpu,計算任務才消耗cpu

所以我們對于你這樣的計算簽名這樣的東西,我們現在通常寫的是

using(steam sm=awaite 異步io給他一個stream)
{
         response xx=await 計算前面(sm)
        string   xxx= await response.getStringAsync()
}

這樣他實際上是3個更小的執行緒,其中前后兩個是IO任務,中間那個是計算任務,當然這些東西因為不涉及的UI部分,所以你可以用ConfigureAwait(false),讓他不去在后續任務程序去捕獲背景關系,已加快切換速度

uj5u.com熱心網友回復:

并行計算是否可縮短時間,也要看任務本身。
單個任務如果已經將你的cpu吃滿了,那么并行計算就沒有什么意義了。
但是如果是以下情況,并行就有明顯優勢了:
任務本身不耗計算資源,但是耗時較長,如需要等待的任務,常見的瀏覽廣告頁面(比如90秒),送積分任務。假如你有1000個賬號要做這個任務,順序執行的話時間大概就是90*1000秒;并行計算必定會快非常多,優化后甚至可以無限接近90s。

uj5u.com熱心網友回復:

parallel. invoke()
我記得可以這樣并行執行

uj5u.com熱心網友回復:

話說,我實際測驗一下,其實并沒有發現你說情況
測驗代碼

 static async Task Main(string[] args)
        {

            string x = string.Join("", Enumerable.Repeat(1, 100));
            Stopwatch watch = new Stopwatch();
            watch.Start();


            await Task.WhenAll(getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x)
            );
            watch.Stop();
            Console.WriteLine(watch.Elapsed.TotalMilliseconds);


            Console.ReadKey();
        }
        static MD5 md5 = MD5.Create();
        public static async Task<string> getMD5(string str)
        {

            using (Stream ms = await CreateStrem(str).ConfigureAwait(false))
            {

                var x = await Task<byte[]>.Run(() =>
                {

                    return md5.ComputeHash(ms);
                }).ConfigureAwait(false);
               
                return UTF8Encoding.UTF8.GetString(x);
            }

        }

        public static Task<Stream> CreateStrem(string x)
        {
            return Task<Stream>.Run(async () =>
            {
                MemoryStream ms = new MemoryStream();
                await ms.WriteAsync(UTF8Encoding.UTF8.GetBytes(x));
                ms.Seek(0, SeekOrigin.Begin);
                return (Stream) ms;


            });


        }


除了統計輸出,我沒有加入其他任何輸出,因為控制臺輸出會干擾統計。

實際結果:單獨運算一個和并發10個沒有任何區別,我測驗機跑一個22ms,跑10個還是22ms。其實22ms對于計算機來說是無壓力的,進的快,走的也快(小學題:一個進水,一個出水。22ms對計算機來說近乎是進水等于出水的節奏,)

ps:22ms是在控制臺直接運行,不是在vs里跑的,vs跑的快要*10,因為vs啟動診斷等等附加開銷

uj5u.com熱心網友回復:

 await Task.WhenAll(getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x)


我加這么多跑,結果75ms,可見他當然是并行的

uj5u.com熱心網友回復:

感謝解答。。經過測驗和找了一些粗淺的資料 嘗試用 如下類似的方法來測驗同時簽名 正常情況下函式執行時間在5ms左右。我測驗同時簽名6條資料(cpu 6核,盡量減低cpu本身能力不足的原因,所以用6條測驗)。實際 測驗下來雖然比逐條運行有所改善,但是遠沒有達到期望的5ms+損耗就能出結果的需求。我粗淺的認為 這里的Parallel 并不是我想要的“并行”。所以想嘗試多行程方案。所以想再次請教2個問題
1,我的測驗是否正確?還是還有其他方案?
2,假設我想要嘗試多行程方案。請推薦一種方案可以么?沒接觸過多行程。因為是想提高并發的簽名速度,所以希望行程間的通訊延遲足夠小,至少ms內其他行程能做出回應并且執行簽名任務后主行程也能最快速度得到回饋。。需兼容Linux/windows平臺。

 Parallel.ForEach(list, new ParallelOptions() { MaxDegreeOfParallelism = 6 }, (i) =>
                {
                    string tmp =  純cpu運算操作簽名異步函式,是一個橢圓ECDSA演算法(1).Result;
                });

uj5u.com熱心網友回復:

很是奇怪。我之前就用task。whenAll做的測驗。測驗結果不但沒有減少簽名時間。反而偶爾有可能比順序總時間還增加了。
我呼叫的簽名如下:不知道您能否幫助看下問題所在。。
using Nethereum.Signer 
簽名代碼
 static EthereumMessageSigner signer = new EthereumMessageSigner();
byte[] array = Encoding.ASCII.GetBytes(message);
  string tmp =  signer.Sign(array, _ethPrivateKey);



參考 6 樓 wanghui0380 的回復:
 await Task.WhenAll(getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x), getMD5(x),
                getMD5(x), getMD5(x)


我加這么多跑,結果75ms,可見他當然是并行的

uj5u.com熱心網友回復:

string tmp =  純cpu運算操作簽名異步函式,是一個橢圓ECDSA演算法(1).Result;

result 是一個同步阻斷操作,他和真異步的區別是,此時你的執行緒還在運行(執行緒有執行緒,這個result就是說該該步操作依然在執行緒調度中輪詢)

真異步是 await 另一個task 或者await 驅動級別的IO信號,此時本執行緒處于掛起狀態或者完成狀態,不參與執行緒調度輪詢,直到他收到信號量或者回呼才會從新執行

其實真await task 是一個狀態機遷移動作
他真實描述是
 (i) =>
                {
                        //這個新執行緒1
                    string tmp =  純cpu運算操作簽名異步函式,是一個橢圓ECDSA演算法(1).Result; //另啟動執行緒,但本執行緒不退出,阻塞拿結果
                       還是這個新執行緒1
                });


 async(i) =>
                {
                        //這個新執行緒1
                    string tmp =await  純cpu運算操作簽名異步函式,是一個橢圓ECDSA演算法(1).     //  另啟動執行緒2,狀態遷移,當前執行緒退出或掛起  ,此刻實際運行  執行緒2,執行緒1已退出   或掛起     
                         //另外執行緒執行完畢,狀態遷移,執行緒2回呼到此或者信號量釋放執行緒1恢復
                });

對比真異步的化你就知道,同步拿結果。他其實是一個阻止更多并行的操作

uj5u.com熱心網友回復:

Sign 以上呼叫的是第三方庫。當時以為sign中會有什么其他操作。我單獨吧Sign抽離出來也是同樣結果。抽離出來的代碼如下。也就是sign的大概流程


public static string Sign(byte[] message, ECDsaSigner _ECDsaSigner, byte[] uncompressedPublicKey/*, ECKey _ecKey*/)
        {
            DateTime d = DateTime.Now;
            DateTime d2 = DateTime.Now;
            var byteList = new List<byte>();
            var bytePrefix = "0x19".HexToByteArray();
            var textBytePrefix = Encoding.UTF8.GetBytes("Ethereum Signed Message:\n" + message.Length);
            byteList.AddRange(bytePrefix);
            byteList.AddRange(textBytePrefix);
            byteList.AddRange(message);
            var plainMessage = byteList.ToArray();
            Console.WriteLine($"步驟:1 {(DateTime.Now - d)}");
            d = DateTime.Now;

            KeccakDigest digest = new KeccakDigest(256);
            byte[] hash = new byte[digest.GetDigestSize()];
            digest.BlockUpdate(plainMessage, 0, plainMessage.Length);
            digest.DoFinal(hash, 0);
            Console.WriteLine($"步驟:2 {(DateTime.Now - d)}");
            d = DateTime.Now;

            var tmp = _ECDsaSigner.GenerateSignature(hash);
            Console.WriteLine($"步驟:3 {(DateTime.Now - d)}");
            d = DateTime.Now;

            var tmp2 = new ECDSASignature(tmp);
            Console.WriteLine($"步驟:4 {(DateTime.Now - d)}");
            d = DateTime.Now;

            var byte_tmp = tmp2.ToDER();
            Console.WriteLine($"步驟:5 {(DateTime.Now - d)}");
            d = DateTime.Now;

            var sig = ECDSASignature.FromDER(byte_tmp);
            Console.WriteLine($"步驟:6 {(DateTime.Now - d)}");
            d = DateTime.Now;

            var ECDSAsignature = sig.MakeCanonical();
            Console.WriteLine($"步驟:7 {(DateTime.Now - d)}");
            d = DateTime.Now;

            var recId = -1;
            for (var i = 0; i < 4; i++)
            {
                ECKey rec = ECKey.RecoverFromSignature(i, ECDSAsignature, hash, false);
                if (rec != null)
                {
                    var k = rec.GetPubKey(false);
                    Console.WriteLine($"步驟:8-{i} {(DateTime.Now - d)}");
                    if (k != null && k.SequenceEqual(uncompressedPublicKey))
                    {
                        recId = i;
                        break;
                    }
                }
            }
            if (recId == -1)
                throw new Exception("Could not construct a recoverable key. This should never happen.");
            Console.WriteLine($"步驟:8 {(DateTime.Now - d)}");
            d = DateTime.Now;

            ECDSAsignature.V = new[] { (byte)(recId + 27) };

            var t2 = "0x" + ECDSAsignature.R.ToByteArrayUnsigned().ToHex().PadLeft(64, '0') +
                   ECDSAsignature.S.ToByteArrayUnsigned().ToHex().PadLeft(64, '0') +
                   ECDSAsignature.V.ToHex();


            Console.WriteLine($"步驟:9 {(DateTime.Now - d)}");
            Debug.WriteLine($"{DateTime.Now.ToString("mm:ss:ffff")} 簽名總耗時 {(DateTime.Now - d2)}");
            return t2;
        }


代碼中有一些檢查簽名耗時的一些嬰兒代碼。別見怪。。~~為了速度還吧一些物件提前實體化,靜態化。隨意引數有所改動。但是實際這些耗時都不高。

最耗時的是var tmp = _ECDsaSigner.GenerateSignature(hash); 和
ECKey rec = ECKey.RecoverFromSignature(i, ECDSAsignature, hash, false);
這兩條陳述句。是個橢圓DSA演算法。。也已經獨立抽離出來。但是沒能力簡化和提高運算速度。。

uj5u.com熱心網友回復:

Parallel在多核(多執行緒)cpu上就是真正的并行,只不過每啟動其中一個任務也是需要時間的, 你別用5ms的任務試, 換用5s的試試.

uj5u.com熱心網友回復:

我覺著你最需要知道的執行緒本身,而不是語法本身。你好像總在繞圈
https://www.zhihu.com/question/42962803

你的知道你的執行緒到底在什么狀態,result同步的情況他一直處于運行態,而async await 其實是本執行緒已死或者掛起(邏輯上我們認為他是掛起狀態,但其實是執行緒已死,如果你在 await task 進入前,執行中,重新運行回來這3個地方輸出執行緒id,你會發現進入前是一個id,重新回來后是另一個id,說明邏輯上好像在同一個大括號里,但實際上他被編輯器編譯成了 傳統的 這種回呼方式)

         執行緒1  
{
                call執行緒2(引數背景關系,回呼方法)//call完了就死了
}

         執行緒2
           {
               有結果了,修改引數背景關系,Call回呼方法(修改后的引數背景關系)
           }

           回呼方法(引數背景關系)
          {
                對,我們這里拿到新結果了,但此時其實在執行緒2里,而不是執行緒1,執行緒1早就死了
          }
 
 這樣你會發現就是我們說的,他拆成更小的任務,同時他在執行狀態中的就1個執行緒。而同步reslut,這個確有兩個執行中的執行緒并且這兩個執行緒還有同步關系

uj5u.com熱心網友回復:

而同步reslut,這個確有兩個執行中的執行緒并且這兩個執行緒還有同步關系

這個就相當于很多人最喜歡用的Thread.Join ,但是這東西的結果就是多出一個執行緒,而且這兩執行緒還不是并行關系,這兩執行緒是串行關系

uj5u.com熱心網友回復:

非常抱歉。。 .Result是在發帖的時候我給特意加上了。理解不夠深。因為我發現
用如下代碼 會造成 Debug.WriteLine($"并行總時間{DateTime.Now - d}"); 執行的過早。。也就是沒能等  Parallel.ForEach 全部執行完成就執行了這個debug輸出。。 因為是測驗。所以沒去學習這門等待Parallel.ForEach完整完成的方法。就想當然的改成.Result 發帖詢問了。。
 Debug.WriteLine("并行 Test start");
                Parallel.ForEach(list, new ParallelOptions() { MaxDegreeOfParallelism = 6 }, async  (i) =>
                {
                    Debug.WriteLine($"并行 {i} 開始 {DateTime.Now.ToString("mm:ss:ffff")}");
                    var tmp = await TestAsync1(1);
                });
                Debug.WriteLine($"并行總時間{DateTime.Now - d}");


參考 9 樓 wanghui0380 的回復:
string tmp =  純cpu運算操作簽名異步函式,是一個橢圓ECDSA演算法(1).Result;

result 是一個同步阻斷操作,他和真異步的區別是,此時你的執行緒還在運行(執行緒有執行緒,這個result就是說該該步操作依然在執行緒調度中輪詢)

真異步是 await 另一個task 或者await 驅動級別的IO信號,此時本執行緒處于掛起狀態或者完成狀態,不參與執行緒調度輪詢,直到他收到信號量或者回呼才會從新執行

其實真await task 是一個狀態機遷移動作
他真實描述是
 (i) =>
                {
                        //這個新執行緒1
                    string tmp =  純cpu運算操作簽名異步函式,是一個橢圓ECDSA演算法(1).Result; //另啟動執行緒,但本執行緒不退出,阻塞拿結果
                       還是這個新執行緒1
                });


 async(i) =>
                {
                        //這個新執行緒1
                    string tmp =await  純cpu運算操作簽名異步函式,是一個橢圓ECDSA演算法(1).     //  另啟動執行緒2,狀態遷移,當前執行緒退出或掛起  ,此刻實際運行  執行緒2,執行緒1已退出   或掛起     
                         //另外執行緒執行完畢,狀態遷移,執行緒2回呼到此或者信號量釋放執行緒1恢復
                });

對比真異步的化你就知道,同步拿結果。他其實是一個阻止更多并行的操作

uj5u.com熱心網友回復:

參考 11 樓 JDD1997 的回復:
Parallel在多核(多執行緒)cpu上就是真正的并行,只不過每啟動其中一個任務也是需要時間的, 你別用5ms的任務試, 換用5s的試試.

額。那么按照我的要求。我只能去尋求多行程的解決方法了么?總覺得多行程可能會有點麻煩。。。Parallel的啟動耗時挺多的么?。另外。請教。假設我task的數量是確定的。能否指定.Parallel的起始數量? 默認有個引數是指定最大并行數。。

uj5u.com熱心網友回復:

參考 15 樓 boyyao 的回復:
Quote: 參考 11 樓 JDD1997 的回復:
Parallel在多核(多執行緒)cpu上就是真正的并行,只不過每啟動其中一個任務也是需要時間的, 你別用5ms的任務試, 換用5s的試試.

額。那么按照我的要求。我只能去尋求多行程的解決方法了么?總覺得多行程可能會有點麻煩。。。Parallel的啟動耗時挺多的么?。另外。請教。假設我task的數量是確定的。能否指定.Parallel的起始數量? 默認有個引數是指定最大并行數。。


你太過糾結語法,先去看執行緒本身。你現在這樣問其實就是執行緒狀態問題。執行緒的第一,第2步狀態是,建立---就緒
然后是等待作業系統調度,等待cpu調度。不是什么啟動耗時挺多,而是由系統根據優先級調度,你用的task.run其實也是多核調度,他是執行緒池,你先進池,然后執行緒池調度器給你調度,執行緒池調度器也是支持多核的。(只是執行緒池比多核出的早,所以執行緒池對多核利用不太充分,所以后面才有Paralle,你不需要要糾結什么Paralle核執行緒,因為Paralle其實依舊是執行緒池,只是對新的多核指令集進行了優化,對,硬體廠家出多核方案后調整了指令集的,對多核特性上出來專用指令集,當然這個都不關你的事情,你只需要做好自己的事情)

做好你自己的事情
1.劃分小任務
2.區分IO任務,cpu任務
3.對于IO任務,請及時釋放物件和記憶體
4.cpu任務,在滿足要求的情況,適當控制并發數量。(池 或者 帶數量控制的phore信號量-------也就是12306的賣票機制,我設計目標達產多少,滿產多少就發多少票,不要超賣,把東西一股腦全扔到執行緒)

  System.Threading.SemaphoreSlim SemaphoreSlim=new SemaphoreSlim(100,200); //達產100,滿產200

還是小學題,一進一出,問多長時間能放完。我們說這取決與你進多少,出多少。當然我得限制進入口徑,不做限制,你進水量是1000,我出水量最多190,結果當然是悲劇

uj5u.com熱心網友回復:

參考 7 樓 boyyao 的回復:
感謝解答。。經過測驗和找了一些粗淺的資料 嘗試用 如下類似的方法來測驗同時簽名 正常情況下函式執行時間在5ms左右。我測驗同時簽名6條資料(cpu 6核,盡量減低cpu本身能力不足的原因,所以用6條測驗)。實際 測驗下來雖然比逐條運行有所改善,但是遠沒有達到期望的5ms+損耗就能出結果的需求。我粗淺的認為 這里的Parallel 并不是我想要的“并行”。所以想嘗試多行程方案。所以想再次請教2個問題
1,我的測驗是否正確?還是還有其他方案?
2,假設我想要嘗試多行程方案。請推薦一種方案可以么?沒接觸過多行程。因為是想提高并發的簽名速度,所以希望行程間的通訊延遲足夠小,至少ms內其他行程能做出回應并且執行簽名任務后主行程也能最快速度得到回饋。。需兼容Linux/windows平臺。

 Parallel.ForEach(list, new ParallelOptions() { MaxDegreeOfParallelism = 6 }, (i) =>
                {
                    string tmp =  純cpu運算操作簽名異步函式,是一個橢圓ECDSA演算法(1).Result;
                });


 string tmp =  純cpu運算操作簽名異步函式,是一個橢圓ECDSA演算法(1).Result;
這個寫法,就是同步。
改成下面的試試看
Parallel.ForEach(list, new ParallelOptions() { MaxDegreeOfParallelism = 6 }, async (i) =>
                {
                    string tmp = await  純cpu運算操作簽名異步函式,是一個橢圓ECDSA演算法(1);
                });

uj5u.com熱心網友回復:

我記得吧。對于單CPU來說,不存在并行,這與語言是無關的。執行緒的增加反而占用了計算資源。
燒水的時候同時掃地正是習以為常的并發,人是cpu,燒水是執行緒、掃地是執行緒。
*傻等水開了再去掃地、和燒水時掃地實際上人這個CPU的作業量是沒有變化的。

你這個作業如果各個任務不存在阻塞/等待/...情況的話。同樣演算法、代碼下,單CPU下不存在提高效率,反而只會增加損耗【執行緒切換...】

思路有三個:
增加CPU/強化CPU
優化演算法
優化代碼
具體我沒經驗,不懂,但方向是這個不會錯

uj5u.com熱心網友回復:

如果是個CPU的計算機,我記得好像也需要一些特定的代碼才能讓執行緒分別并行作業起來,也就是也需要對應代碼形式,否則不一定完全在并發。
以前學習時了解的,不知道有沒有記錯

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/276497.html

標籤:C#

上一篇:多執行緒的問題

下一篇:C# 給DataGridView的column定制DefaultCellStyle代碼問題

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more