<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 26章 C99的限制 這個例子說明了為什么某些情況下FORTRAN的速度比C/C++要快 ``` #!cpp void f1 (int* x, int* y, int* sum, int* product, int* sum_product, int* update_me, size_t s) { for (int i=0; i<s; i++) { sum[i]=x[i]+y[i]; product[i]=x[i]*y[i]; update_me[i]=i*123; // some dummy value sum_product[i]=sum[i]+product[i]; }; }; ``` 這是一個十分簡單的例子,但是有一點需要注意:指向update_me數組的指針也可以指向sum數組,甚至是sum_product數組。但是這不是嚴重的錯誤,對嗎? 編譯器很清楚這一點,所以他在循環體中產生了四個階段: 1.計算下一個sum[i] 2.計算下一個product[i] 3.計算下一個unpdate_me[i] 4.計算下一個sum_product[i],在這個階段,我們需要從已經計算過sum[i]和product[i]的內存中載入數據 最后一個階段可以優化嗎?既然已經計算過的sum[i]和product[i]是不需要再次從內存裝載的(因為我們已經計算過他們了)。但是編譯器不能保證在第三個階段沒有東西被覆蓋掉!這就叫“指針別名”,在這種情況下編譯器無法確定指針指向區域的內存是否已經被改變。 C99標準中的限制給解決這一問題帶來了一線曙光。由設計器傳送給編譯器的函數單元在標記這種關鍵字(restrict)后,它會指向不同的內存區域,并且不 會被混用。 如果要更加準確地描述這種情況,restrict表明了只有指針是可以訪問對象的。這樣的話我們可以通過特定的指針進行工作,并且不會用到其他指針。也就是說一個對象如果被標記為restrict,那么它只能通過一個指針訪問。 我們把每個指向變量的指針標記為restrict關鍵字: ``` #!cpp void f2 (int* restrict x, int* restrict y, int* restrict sum, int* restrict product, int* restrict sum_product, int* restrict update_me, size_t s) { for (int i=0; i<s; i++) { sum[i]=x[i]+y[i]; product[i]=x[i]*y[i]; update_me[i]=i*123; // some dummy value sum_product[i]=sum[i]+product[i]; }; }; ``` 來看下結果: 清單26.1: GCC x64: f1() ``` #!bash f1: push r15 r14 r13 r12 rbp rdi rsi rbx mov r13, QWORD PTR 120[rsp] mov rbp, QWORD PTR 104[rsp] mov r12, QWORD PTR 112[rsp] test r13, r13 je .L1 add r13, 1 xor ebx, ebx mov edi, 1 xor r11d, r11d jmp .L4 .L6: mov r11, rdi mov rdi, rax .L4: lea rax, 0[0+r11*4] lea r10, [rcx+rax] lea r14, [rdx+rax] lea rsi, [r8+rax] add rax, r9 mov r15d, DWORD PTR [r10] add r15d, DWORD PTR [r14] mov DWORD PTR [rsi], r15d ; store to sum[] mov r10d, DWORD PTR [r10] imul r10d, DWORD PTR [r14] mov DWORD PTR [rax], r10d ; store to product[] mov DWORD PTR [r12+r11*4], ebx ; store to update_me[] add ebx, 123 mov r10d, DWORD PTR [rsi] ; reload sum[i] add r10d, DWORD PTR [rax] ; reload product[i] lea rax, 1[rdi] cmp rax, r13 mov DWORD PTR 0[rbp+r11*4], r10d ; store to sum_product[] jne .L6 .L1: pop rbx rsi rdi rbp r12 r13 r14 r15 ret ``` 清單26.2: GCC x64: f2() ``` #!bash f2: push r13 r12 rbp rdi rsi rbx mov r13, QWORD PTR 104[rsp] mov rbp, QWORD PTR 88[rsp] mov r12, QWORD PTR 96[rsp] test r13, r13 je .L7 add r13, 1 xor r10d, r10d mov edi, 1 xor eax, eax jmp .L10 .L11: mov rax, rdi mov rdi, r11 .L10: mov esi, DWORD PTR [rcx+rax*4] mov r11d, DWORD PTR [rdx+rax*4] mov DWORD PTR [r12+rax*4], r10d ; store to update_me[] add r10d, 123 lea ebx, [rsi+r11] imul r11d, esi mov DWORD PTR [r8+rax*4], ebx ; store to sum[] mov DWORD PTR [r9+rax*4], r11d ; store to product[] add r11d, ebx mov DWORD PTR 0[rbp+rax*4], r11d ; store to sum_product[] lea r11, 1[rdi] cmp r11, r13 jne .L11 .L7: pop rbx rsi rdi rbp r12 r13 ret ``` 被編譯過的f1()和f2()的不同點是:在f1()中,sum[i]和product[i]在循環中途被裝入,但是在f2()中沒有這樣的特性。已經計算過的變量將被使用,既然我們已經向編譯器“保證”在循環執行期間,sum[i]和product[i]不會發生改變,所以編譯器“確信”變量的值不用從內存被再裝入。很明顯,第二個例子的程序更快。 但是如果函數變量中的指針發生混淆的情況又能如何呢?這與一個程序員的認知有關,并且結果是不正確的。 回到FORTRAN。FORTRAN語言編譯器按照指針的本身含義對待他,所以當FORTRAN程序在這種情況下不可能使用restrict的時候,它可以生成生成執行更快的代碼。 這有什么實用價值?當函數處理內存中很多大“塊”的時候,比如說用超級計算機解決線性代數問題。或許這就是為什么FORTRAN語言還在這個領域被使用。 但是當迭代步驟不是很多的時候,速度的增加并不是顯著的。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看