<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>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 同步,第 6 部分:實現障礙 > 原文:<https://github.com/angrave/SystemProgramming/wiki/Synchronization%2C-Part-6%3A-Implementing-a-barrier> ## 在繼續下一步之前,如何等待 N 個線程達到某個點? 假設我們想要執行具有兩個階段的多線程計算,但我們不希望在第一階段完成之前進入第二階段。 我們可以使用稱為 **barrier** 的同步方法。當一個線程到達一個屏障時,它將在屏障處等待,直到所有線程都到達屏障,然后它們將一起進行。 把它想象成和一些朋友一起去遠足。你同意在每個山頂上等待對方(并且你會記下你的小組中有多少人)。說你是第一個到達第一座山頂的人。你會在那里等你的朋友。一個接一個,他們將到達頂部,但沒有人會繼續,直到你的小組中的最后一個人到達。一旦他們這樣做,你們都會繼續前進。 Pthreads 有一個實現它的函數`pthread_barrier_wait()`。你需要聲明一個`pthread_barrier_t`變量并用`pthread_barrier_init()`初始化它。 `pthread_barrier_init()`將參與屏障的線程數作為參數。 [這是一個例子。](https://github.com/angrave/SystemProgramming/wiki/Sample-program-using-pthread-barriers) 現在讓我們實現自己的障礙,并使用它來保持所有線程在大型計算中同步。 ```c double data[256][8192] 1 Threads do first calculation (use and change values in data) 2 Barrier! Wait for all threads to finish first calculation before continuing 3 Threads do second calculation (use and change values in data) ``` 螺紋功能有四個主要部分 - ```c void *calc(void *arg) { /* Do my part of the first calculation */ /* Am I the last thread to finish? If so wake up all the other threads! */ /* Otherwise wait until the other threads has finished part one */ /* Do my part of the second calculation */ } ``` 我們的主線程將創建 16 個線程,我們將每個計算分成 16 個單獨的部分。每個線程都將被賦予一個唯一值(0,1,2,... 15),因此它可以在自己的塊上工作。由于(void *)類型可以包含小整數,我們將通過將它轉換為 void 指針來傳遞`i`的值。 ```c #define N (16) double data[256][8192] ; int main() { pthread_t ids[N]; for(int i = 0; i < N; i++) pthread_create(&ids[i], NULL, calc, (void *) i); ``` 注意,我們永遠不會將此指針值取消引用作為實際的內存位置 - 我們只是將其直接轉換回整數: ```c void *calc(void *ptr) { // Thread 0 will work on rows 0..15, thread 1 on rows 16..31 int x, y, start = N * (int) ptr; int end = start + N; for(x = start; x < end; x++) for (y = 0; y < 8192; y++) { /* do calc #1 */ } ``` 計算 1 完成后,我們需要等待較慢的線程(除非我們是最后一個線程!)。因此,請跟蹤到達我們屏障的線程數量'checkpoint': ```c // Global: int remain = N; // After calc #1 code: remain--; // We finished if (remain ==0) {/*I'm last! - Time for everyone to wake up! */ } else { while (remain != 0) { /* spin spin spin*/ } } ``` 但是上面的代碼有一個競爭條件(兩個線程可能會嘗試減少`remain`)并且循環是一個繁忙的循環。我們可以做得更好!讓我們使用一個條件變量然后我們將使用廣播/信號函數來喚醒睡眠線程。 提醒一下,條件變量類似于房子!線程去那里睡覺(`pthread_cond_wait`)。您可以選擇喚醒一個線程(`pthread_cond_signal`)或所有線程(`pthread_cond_broadcast`)。如果當前沒有線程正在等待,則這兩個調用無效。 條件變量版本通常非常類似于忙循環不正確的解決方案 - 我們將在下面展示。首先,讓我們添加一個互斥和條件全局變量,不要忘記在`main`中初始化它們...... ```c //global variables pthread_mutex_t m; pthread_cond_t cv; main() { pthread_mutex_init(&m, NULL); pthread_cond_init(&cv, NULL); ``` 我們將使用互斥鎖來確保一次只有一個線程修改`remain`。最后到達的線程需要喚醒 _ 所有 _ 休眠線程 - 所以我們將使用`pthread_cond_broadcast(&cv)`而不是`pthread_cond_signal` ```c pthread_mutex_lock(&m); remain--; if (remain ==0) { pthread_cond_broadcast(&cv); } else { while(remain != 0) { pthread_cond_wait(&cv, &m); } } pthread_mutex_unlock(&m); ``` 當一個線程進入`pthread_cond_wait`時,它會釋放互斥鎖并休眠。在將來的某個時刻,它會被喚醒。一旦我們從睡眠中恢復一個線程,在返回之前它必須等到它可以鎖定互斥鎖。請注意,即使睡眠線程提前醒來,它也會檢查 while 循環條件并在必要時重新進入等待狀態。 **上面的障礙是不可重用的**意味著如果我們將它粘貼到任何舊的計算循環中,那么代碼很可能會遇到障礙要么死鎖,要么線程在一次迭代中前進更快的情況。考慮如何使上述障礙可重用,這意味著如果多個線程在循環中調用`barrier_wait`,那么可以保證它們在同一個迭代中。
                  <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>

                              哎呀哎呀视频在线观看