學習電腦組成原理有什麼用,意義何在?

来源:https://www.cnblogs.com/AD-milk/archive/2020/06/20/13171059.html
-Advertisement-
Play Games

學習電腦組成原理有什麼用? 從StackOverFlow上一個很經典的問題說起 運行下麵的程式,然後比較加上Arrays.sort(data)這行之後,程式速度的變化 import java.util.Arrays; import java.util.Random; public class Te ...


學習電腦組成原理有什麼用?

從StackOverFlow上一個很經典的問題說起

運行下麵的程式,然後比較加上Arrays.sort(data)這行之後,程式速度的變化

import java.util.Arrays;
import java.util.Random;

public class Test
{
    public static void main(String[] args)
    {
        // Generate data
        int arraySize = 32768;
        int data[] = new int[arraySize];

        Random rnd = new Random(0);
        for (int c = 0; c < arraySize; ++c)
            data[c] = rnd.nextInt() % 256;

        // !!! With this, the next loop runs faster
        //Arrays.sort(data);

        // Test
        long start = System.nanoTime();
        long sum = 0;

        for (int i = 0; i < 100000; ++i)
        {
            // Primary loop
            for (int c = 0; c < arraySize; ++c)
            {
                if(data[c]>128)
                    sum+=data[c];
            }
        }

        System.out.println((System.nanoTime() - start) / 1000000000.0);
        System.out.println("sum = " + sum);
    }
}

在我的電腦上,對數組排序後程式運行速度是原來的四倍,這就奇了怪了,怎麼排個序就快了這麼多?你可能模模糊糊知道應該往計組的方面想,要從底層找原因,畢竟這篇博文就是試圖向你說明瞭解計組有什麼用。

現在將排序註釋掉,並把primary loop裡面的代碼換成

 			   int t = (data[c] - 128) >> 31;
               sum += ~t & data[c];

再次運行程式,你會發現程式運行的時間跟排序後的運行時間差不多,甚至還快一點。有意思吧,通過前面的兩次改動,我們已經把問題鎖定在了Primary loop這裡,現在看來是if語句搞的鬼。沒想到這個平日里看起來濃眉大眼,人畜無害的東西也會給我玩花樣,想不到想不到。

為了快點寫完作業,我選擇瞎蒙

現代電腦的設計,在提高運行速度這塊想出了很多辦法,cache絕對算的上是最精彩的那一個。不過跟本問題相關的是流水線的設計,我們還是先來認識這熟悉又陌生的詞語吧。

流水線是一種實現多條指令重疊執行的技術,你可以類比於生產流水線。

類似於這樣,大家印象中的流水線都是高速運轉的,沒有人希望它停頓。如果流水線存在分支的話,按照常理來講,我們只能是停下來等結果。等比較的結果出來了,再決定走哪條分支 。流水線說,我是一個永不止步的男人,怎麼能因為這點事就停頓呢?忍不了,咋整呢?

有一種辦法是分支冒險(branch hazard),雖然名字聽起來很高大上,其實就是賭一把,蒙一個。我假設這個分支發生,賭對了自然什麼都不用做,賭錯了就得丟棄假設不發生之後執行的指令。這有點像趕作業的時候,碰到判斷題如果你不想做的話,就一路打×,因為這種題目大概率打叉的情況多。當然,電腦沒有你那麼聰明不知道這條規律,但它可以使用動態分支預測的方法來提高預測的準確性。

這裡介紹兩位預測位機制,猜錯兩次就變換猜測方向。

讓我們再來回憶一下之前的實常式序的流程,在0-256的範圍隨機生成了一個數組,並且將大於128的值加到sum變數中。現在,讓我們用剛剛學到的知識分析那條萬惡的if語句

                if(data[c]>128)
                    sum+=data[c];

累計兩次預測失敗我們就會變換預測方向,如果不對數組進行排序的話,數組中的數字是隨機分佈的,我們預測的準確性將會非常低。這意味著我們將會耗費大量的時間在:將流水線中投機執行的中間結果全部拋棄,重新獲取正確分支路線上的指令執行。如果是已經排好序的數組,最壞的情況下我們也只有四次預測失敗,這為我們節省了大把的時間。這也是為什麼我們換成位運算,程式會更快的原因。因為不會存在預測失敗重新執行的情況。

好像和我程式里寫的不一樣

public class Thread01 implements Runnable {
    private int cnt=10;

    @Override
    public void run() {
        while (cnt>0){
        System.out.println(Thread.currentThread().getName()+" cnt= "+cnt--);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Thread01 thread01=new Thread01();
        Thread a=new Thread(thread01,"a");
        Thread b=new Thread(thread01,"b");
        Thread c=new Thread(thread01,"c");
        Thread d=new Thread(thread01,"d");
        Thread e=new Thread(thread01,"e");
        a.start();
        b.start();
        c.start();
        d.start();
        e.start();
    }
}

運行這段程式,你會發現有兩個線程輸出了同樣的數字,按道理這是絕對不可能發生的事情。還是電腦惹的鍋,因為CPU訪問緩存區比訪問記憶體要快得多,所以為了高效,現代電腦往往會在高速緩存區中緩存共用變數。

也就是說,大家各搞各的,這與cache的寫回操作有關(保險的辦法當然是寫直達,但咱不是為了快嘛,所以就出問題了)。有可能你修改的時候,來不及通知我這個值已經不能用了,要重新獲取,最後的結果就是輸出了兩個一模一樣的值。

多線程的東西很多:重排序,記憶體屏障,CAS....感興趣的同學可以查閱相關資料,這篇博文只是拋磚引玉而已。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Vue 給mapState中定義的屬性賦值報錯的解決方案 by:授客 QQ:1033553122 1. 實踐環境 Vue 2.9.6 2. 問題描述 <script> import { mapState } from 'vuex'; export default { name: "displayCo ...
  • Vue 根據滑鼠懸停目標元素上方顯示、隱藏指定元素交互實現 By:授客 QQ:1033553122 開發環境 win10 element-ui "2.13.1" vue "2.6.10" 需求描述 如下,滑鼠移動到左側標簽名稱時,右側展示刪除按鈕,否則不顯示 關鍵實現代碼如下: <template> ...
  • Vue 在父(子)組件引用其子(父)組件方法和屬性 by:授客 QQ:1033553122 開發環境 Win 10 element-ui "2.8.2" Vue 2.9.6 父組件代碼 <template> <div> <button @click="callChildMethod()">父組件調用 ...
  • Vue 阻止事件冒泡 by:授客 QQ:1033553122 開發環境 Win 10 element-ui "2.8.2" Vue 2.9.6 事件冒泡簡介 如下圖,當我們點擊頁面某個元素時,會產生點擊事件,事件由外到內,逐層遞進(事件捕獲階段,途中的1->2->3->4),當目標元素捕捉到目標事件 ...
  • 前後端分離的開發模式讓前端開發者的地位日益提升,待遇水漲船高,這又吸引了一撥人慕名學習前端課程,希望能在前端領域大展巨集圖。 但一個殘酷的現實是市場上不缺普通前端開發,缺的是掌握專業技能的優秀前端工程師。 優秀的前端工程師和普通前端工程師相比有哪些區別?憑什麼優秀的前端工程師就比普通前端工程師多占據那 ...
  • 利用深度優先遍歷和遞歸 var acceptUnitNodes = null;//接收單位樹形數據 function findParentNode(ids){ //ids 是子節點數組 var parentNodes = [];//所有父節點 var forfun = function (id,no ...
  • urls urls中使用 1 urlpatterns = [ 2 path('admin/', admin.site.urls), 3 path('polls/', include('polls.urls', namespace='polls')), 4 ] View Code 運行後報錯,錯誤代碼 ...
  • 一、操作系統環境 可通過以下命令來查看操作系統的具體版本,本例中採用的是CentOS 7.6。一般來說,CentOS中預設已經安裝有python2.x,因為有一些系統命令可能會需要用到python2,所以不能卸載。我們只需再安裝python3.x即可。 # cat /etc/redhat-relea ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...