omp parallel เทียบกับ omp parallel สำหรับ


105

สองตัวนี้ต่างกันอย่างไร?

[A]

#pragma omp parallel
{ 
    #pragma omp for
    for(int i = 1; i < 100; ++i)
    {
        ...
    }
}

[B]

#pragma omp parallel for
for(int i = 1; i < 100; ++i)
{
   ...
}

คำตอบ:


65

ฉันไม่คิดว่ามีความแตกต่างอันหนึ่งเป็นทางลัดสำหรับอีกทางหนึ่ง แม้ว่าการใช้งานที่แน่นอนของคุณอาจจัดการกับสิ่งเหล่านี้แตกต่างกัน

โครงสร้างการแชร์แบบขนานรวมกันเป็นทางลัดสำหรับการระบุโครงสร้างแบบขนานที่มีโครงสร้างการแชร์งานเดียวและไม่มีคำสั่งอื่น ๆ อนุประโยคที่ได้รับอนุญาตคือการรวมกันของอนุประโยคที่อนุญาตสำหรับการสร้างแบบขนานและการแชร์เวิร์คแชร์

นำมาจากhttp://www.openmp.org/mp-documents/OpenMP3.0-SummarySpec.pdf

ข้อกำหนดสำหรับ OpenMP อยู่ที่นี่:

https://openmp.org/specifications/


66

สิ่งเหล่านี้เทียบเท่า

#pragma omp parallelสร้างกลุ่มของเธรดในขณะที่#pragma omp forแบ่งการวนซ้ำแบบวนซ้ำระหว่างเธรดที่เกิด คุณสามารถทำทั้งสองอย่างพร้อมกันได้ด้วย#pragma omp parallel forคำสั่งผสม


ในรหัสของฉันฉันใช้โครงสร้างนี้ อย่างไรก็ตามเมื่อฉันใช้schedule(static, chunk)clause in สำหรับ directive ฉันพบปัญหา รหัสทำงานได้ดี แต่เมื่อฉันเรียกใช้รหัสนี้จากโปรแกรม MPI มันจะทำงานในวงวนไม่สิ้นสุด ตัวนับลูปเป็นศูนย์ในการวนซ้ำทั้งหมดของลูปนี้ ฉันมีตัวนับลูปที่กำหนดให้เป็นส่วนตัวใน#pragma omp parallelคำสั่ง ไม่รู้ว่าทำไมมันถึงล้มเหลวเมื่อ MPI เรียกใช้รหัสเท่านั้น ฉันค่อนข้างแน่ใจว่าแต่ละกระบวนการ MPI กำลังทำงานบนโปรเซสเซอร์ที่แตกต่างกันของคลัสเตอร์หากเป็นเช่นนั้น ไม่รู้ว่ากำหนดการทำให้เกิดปัญหาหรือไม่
Rohit Banga

สิ่งเดียวกันทำงานได้ดีเมื่อฉันใช้#pragma omp parallel forคำสั่ง ควรจะมีความแตกต่างบ้าง
Rohit Banga

1
อัปเดต: ตามที่ปรากฎฉันสังเกตเห็นปัญหานี้เฉพาะเมื่อฉันใช้ประโยคกำหนดการดังนั้นฉันเดาว่ามันไม่ได้ขึ้นอยู่กับว่าฉันใช้คู่ขนานรวมสำหรับหรือสองคำสั่งที่แตกต่างกัน
Rohit Banga

29

นี่คือตัวอย่างของการใช้แยกออกจากกันparallelและที่นี่for ในระยะสั้นสามารถใช้สำหรับการจัดสรรแบบไดนามิกของอาร์เรย์เธรดส่วนตัว OpenMP ก่อนที่จะดำเนินการforรอบในหลายเธรด เป็นไปไม่ได้ที่จะทำการเริ่มต้นในparallel forกรณีเดียวกัน

UPD: ในตัวอย่างคำถามไม่มีความแตกต่างระหว่าง pragma เดียวและสอง pragmas แต่ในทางปฏิบัติคุณสามารถสร้างพฤติกรรมการรับรู้เธรดได้มากขึ้นด้วยการแยกคู่ขนานและสำหรับคำสั่ง บางรหัสเช่น:

#pragma omp parallel
{ 
    double *data = (double*)malloc(...); // this data is thread private

    #pragma omp for
    for(1...100) // first parallelized cycle
    {
    }

    #pragma omp single 
    {} // make some single thread processing

    #pragma omp for // second parallelized cycle
    for(1...100)
    {
    }

    #pragma omp single 
    {} // make some single thread processing again

    free(data); // free thread private data
}

10

แม้ว่าตัวอย่างเฉพาะทั้งสองเวอร์ชันจะเทียบเท่ากันดังที่ได้กล่าวไปแล้วในคำตอบอื่น ๆ แต่ก็ยังมีความแตกต่างเล็กน้อยระหว่างกัน เวอร์ชันแรกมีอุปสรรคโดยนัยที่ไม่จำเป็นซึ่งพบในตอนท้ายของ "omp for" อุปสรรคโดยนัยอื่น ๆ สามารถพบได้ที่ส่วนท้ายของพื้นที่คู่ขนาน การเพิ่ม "nowait" เป็น "omp for" จะทำให้รหัสทั้งสองเทียบเท่ากันอย่างน้อยก็จากมุมมองของ OpenMP ฉันพูดถึงสิ่งนี้เนื่องจากคอมไพเลอร์ OpenMP สามารถสร้างรหัสที่แตกต่างกันเล็กน้อยสำหรับสองกรณี


7

ฉันเห็นเวลาทำงานที่แตกต่างกันอย่างสิ้นเชิงเมื่อฉันใช้ for loop ใน g ++ 4.7.0 และใช้

std::vector<double> x;
std::vector<double> y;
std::vector<double> prod;

for (int i = 0; i < 5000000; i++)
{
   double r1 = ((double)rand() / double(RAND_MAX)) * 5;
   double r2 = ((double)rand() / double(RAND_MAX)) * 5;
   x.push_back(r1);
   y.push_back(r2);
}

int sz = x.size();

#pragma omp parallel for

for (int i = 0; i< sz; i++)
   prod[i] = x[i] * y[i];

รหัสซีเรียล (no openmp) ทำงานใน 79 ms โค้ด "parallel for" ทำงานใน 29 มิลลิวินาที หากฉันละเว้นforและใช้#pragma omp parallelรันไทม์จะยิงได้ถึง 179ms ซึ่งช้ากว่ารหัสซีเรียล (เครื่องมี hw พร้อมกัน 8)

รหัสเชื่อมโยงไปยัง libgomp


2
ฉันคิดว่ามันเป็นเพราะ omp parallel ดำเนินการวนซ้ำในเธรดที่แยกจากกันโดยไม่แบ่งเป็นเธรดดังนั้นเธรดหลักจึงรอให้เธรดที่สองเสร็จสิ้น และเวลาที่ใช้ในการซิงโครไนซ์
Antigluk

7
นั่นเป็นเพราะหากไม่มี#pragma omp forจะไม่มีการแชร์ลูปแบบมัลติเธรดเลย แต่นั่นไม่ใช่กรณี OPs ลองอีกครั้งโดยมีตัวเลือกเพิ่มเติม#pragma omp forภายใน#pragm omp parallelและควรทำงานคล้ายกัน (ถ้าไม่เหมือนกัน) เหมือน#pragma omp parallel forเวอร์ชัน
Christian Rau

2
ฉันเห็นว่าคำตอบนี้ดีที่สุดเนื่องจากแสดงว่าไม่ "เทียบเท่า"
Failed Scientist

7

เห็นได้ชัดว่ามีคำตอบมากมาย แต่คำตอบนี้ตอบได้ดีมาก (พร้อมแหล่งที่มา)

#pragma omp forมอบหมายเฉพาะบางส่วนของลูปสำหรับเธรดที่แตกต่างกันในทีมปัจจุบัน ทีมคือกลุ่มของเธรดที่เรียกใช้โปรแกรม เมื่อเริ่มโปรแกรมทีมประกอบด้วยสมาชิกคนเดียวเท่านั้น : เธรดหลักที่รันโปรแกรม

ในการสร้างทีมเธรดใหม่คุณต้องระบุคีย์เวิร์ดคู่ขนาน สามารถระบุได้ในบริบทโดยรอบ:

#pragma omp parallel
{
   #pragma omp for
   for(int n = 0; n < 10; ++n)
   printf(" %d", n);
}

และ:

อะไรคือคู่ขนานสำหรับและทีม

ความแตกต่างระหว่างขนานขนานสำหรับและสำหรับมีดังนี้:

ทีมคือกลุ่มของเธรดที่ดำเนินการในปัจจุบัน ในตอนเริ่มต้นโปรแกรมทีมประกอบด้วยเธรดเดียว โครงสร้างแบบขนานจะแยกเธรดปัจจุบันออกเป็นทีมเธรดใหม่ในช่วงระยะเวลาของบล็อก / คำสั่งถัดไปหลังจากนั้นทีมจะรวมกลับเป็นกลุ่มเดียวกัน สำหรับแบ่งงานของ for-loop ระหว่างเธรดของทีมปัจจุบัน

มันไม่ได้สร้างเธรด แต่จะแบ่งงานระหว่างเธรดของทีมที่ดำเนินการอยู่ในปัจจุบันเท่านั้น ขนานสำหรับคือชวเลขสำหรับสองคำสั่งพร้อมกัน: ขนานและสำหรับ. Parallel สร้างทีมใหม่และสำหรับการแยกทีมนั้นเพื่อจัดการกับส่วนต่างๆของลูป ถ้าโปรแกรมของคุณไม่เคยมีโครงสร้างแบบขนานแสดงว่ามีเธรดไม่เกินหนึ่งเธรด เธรดหลักที่เริ่มต้นโปรแกรมและรันเช่นเดียวกับในโปรแกรมที่ไม่ใช่เธรด

https://bisqwit.iki.fi/story/howto/openmp/

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.