เมื่อไรที่จะใช้ Parallel Arrays?


14

ฉันใช้รหัส (รหัสใหม่) ที่ใช้สิ่งที่ฉันเรียกว่า 'อาร์เรย์แบบขนาน' หรือรายการ ความหมายมี 2 อาร์เรย์ที่มีข้อมูลที่เกี่ยวข้องและเชื่อมโยงโดยตำแหน่ง (ดัชนี) ในอาร์เรย์

ฉันพิจารณาถึงความสับสนและมีแนวโน้มที่จะเกิดข้อผิดพลาดทุกประเภท วิธีแก้ปัญหาที่ฉันเสนอตามปกติคือการสร้างวัตถุที่เรียกว่าCompanyมีฟิลด์ CompanyId และ CompanyName

ตัวอย่างจริงมาก:

List<string> companyNames;
List<int> companyIds;

//...They get populated somewhere and we then process

for(var i=0; i<companyNames.Count; i++)
{
    UpdateCompanyName(companyIds[i],companyNames[i]);
}

อาร์เรย์แบบขนานเหล่านี้มีการพิจารณาว่าไม่เหมาะสมหรือไม่


9
เพียงพิสูจน์เพิ่มเติมว่าไม่มีการประดิษฐ์ภาษาใดที่คุณไม่สามารถเขียน Fortran ได้
มะม่วงแอนดี้

3
มีประโยชน์ค่อนข้างมากในการทำสิ่งนี้ (แม้ว่าคุณจะต้องใช้อาร์เรย์ที่ต่อเนื่องกันซึ่งไม่ได้เชื่อมโยงกับรายการ) และสิ่งนี้ก็ได้รับความนิยมในการเขียนโปรแกรมเกมที่เกี่ยวข้องกับ "การออกแบบเชิงข้อมูล" อย่างไรก็ตามสิ่งนี้ดูเหมือนจะไม่ใช้กับกรณีของคุณ ดูเหมือนว่าคุณกำลังสร้างโค้ดที่มีประสิทธิภาพที่สำคัญ
Derek Elkins ออกจาก SE

2
@DerekElkins ... น่าสนใจว่าความคิดเห็นของคุณเป็นไปตามการเปรียบเทียบกับรหัส Fortran รุ่นก่อนหน้าของ Fortran ขาดการสนับสนุนสำหรับโครงสร้างที่ผู้ใช้กำหนดและแม้กระทั่งหลังจากที่มันถูกเพิ่มรหัส Fortran ที่ใช้สำนวนใช้หลายอาร์เรย์ของคุณสมบัติไม่ใช่อาร์เรย์ของโครงสร้าง และนี่คือเครดิตมักเป็นส่วนหนึ่งของเหตุผลที่ Fortran มักจะถือว่าเป็นภาษาที่เร็วที่สุด
Jules

3
ความคิดเชิงสัมผัสสำหรับคำถามนี้: ภาษาที่ใช้งานได้หลายภาษากระตุ้นให้ทำงานกับรายการดังกล่าว พวกมันมีฟังก์ชั่นที่เรียกว่า zip ซึ่งจะแปลงพวกมันให้เป็นรายการของ tuples รหัสของคุณดูเหมือน C # เวอร์ชันล่าสุดของ C # ได้เพิ่มการรองรับสำหรับอันดับหนึ่ง ฉันสงสัยว่าดังนั้นพวกเขาได้เพิ่มฟังก์ชั่นซิปบางแห่งที่สามารถทำให้รายการของคุณเป็นโครงสร้างที่มีประโยชน์สำหรับคุณโดยอัตโนมัติหรือไม่?
จูลส์

4
บางครั้งมีเหตุผลในการใช้สองอาร์เรย์โดยเจตนา แต่ใน 99% ของทุกกรณีที่ฉันได้เห็นสิ่งนี้เหตุผลเพียงอย่างเดียวคือความขี้เกียจของผู้เขียนต้นฉบับที่จะแนะนำโครงสร้างข้อมูลที่ไพบูลย์
Doc Brown

คำตอบ:


23

นี่คือเหตุผลบางประการที่บางคนอาจใช้อาร์เรย์ของถังน้ำ:

  1. ในภาษาที่ไม่สนับสนุนคลาสหรือ structs
  2. เพื่อหลีกเลี่ยงการล็อกเธรดเมื่อแต่ละเธรดกำลังแก้ไขหนึ่งคอลัมน์เท่านั้น
  3. เมื่อวิธีการเก็บรักษาบังคับให้สิ่งเหล่านี้ถูกจัดเก็บแยกต่างหากและคุณกำลังสร้างใหม่อีกครั้ง
  4. พวกเขาสามารถใช้หน่วยความจำน้อยลงหากโครงสร้างมีเบาะ (ไม่สามารถใช้ได้กับประเภทข้อมูลเหล่านี้ใน C #)
  5. เมื่อจำเป็นต้องเก็บข้อมูลบางส่วนไว้ใกล้กันเพื่อให้การใช้งาน CPU แคชมีประสิทธิภาพ (จะไม่ช่วยในรหัสด้านบน)
  6. การใช้รหัส op การสอนหลายข้อมูลเดียว (SIMD) (ไม่สามารถใช้กับรหัสนี้หรือสตริงได้เลย)

ฉันไม่เห็นเหตุผลที่น่าสนใจในการทำสิ่งนี้ในกรณีนี้ ... และมีตัวเลือกที่ดีกว่าในทุกข้อที่กล่าวมาข้างต้นหรือไม่มีประโยชน์ในภาษาระดับสูง


3
พวกเขาสามารถใช้หน่วยความจำน้อยลงเช่นกันหากโครงสร้างมีเบาะ อาร์เรย์ขนาดใหญ่จำนวนมากที่จัดสรรไว้อย่างชาญฉลาดสามารถใช้หน่วยความจำน้อยกว่าอาร์เรย์โครงสร้าง
Frank Hileman

4
4. เมื่อต้องเก็บส่วนต่าง ๆ ของข้อมูลไว้ใกล้กันเพื่อใช้งาน CPU แคชอย่างมีประสิทธิภาพ (จำเป็นในบางกรณี)
Blrfl

@ Frank Hileman, Whilie ฉันคิดว่าคำตอบของ TheCatWhisperer นั้นถูกต้องสมบูรณ์ความคิดเห็นของคุณคือจริง ๆ แล้วเหตุผลที่ดีที่สุดในการเลือกวิธีการนี้ ถ้าปริมาณการใช้หน่วยความจำมีความสำคัญโอเวอร์เฮดของหน่วยความจำในโครงสร้าง padding อาจมีความสำคัญ
Vladimir Stokic

เพิ่มคำแนะนำของคุณลงในคำตอบ
TheCatWhisperer

Re (2) เป็นอย่างไร ฉันสามารถเขียนโปรแกรมที่มีโครงสร้างแบบอาร์เรย์เดียวและล็อคต่อฟิลด์ได้อย่างง่ายดายเหมือนกับที่ฉันสามารถเขียนโปรแกรมที่มีหลายอาร์เรย์และล็อคต่ออาร์เรย์
โซโลมอนช้า

7

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

ณ จุดนี้ถึงแม้ว่าจะคุ้มค่าที่จะพิจารณาการปรับโครงสร้างใหม่เพื่อให้รายละเอียดที่เป็นนามธรรมออกไป บ่อยครั้งที่เหตุผลที่ยิ่งใหญ่ที่สุดที่ฉันลังเลที่จะทำมันกลับกลายเป็นว่ามันยากที่จะคิดชื่อที่ดี

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


6

รูปแบบนี้บางครั้งเรียกว่าโครงสร้างของอาร์เรย์ (เมื่อเทียบกับ Array of Structures) และมีประโยชน์อย่างยิ่งเมื่อโค้ด vectorizing แทนที่จะเขียนการคำนวณที่ทำงานบนโครงสร้างเดียวและบิต vectorizing ของมันคุณเขียนการคำนวณตามปกติยกเว้น SSE ที่แท้จริงเพื่อให้ทำงานบน 4 โครงสร้างแทนหนึ่ง ซึ่งมักจะง่ายกว่าและเกือบจะเร็วกว่าเสมอ รูปแบบ SOA ทำให้สิ่งนี้เป็นธรรมชาติมาก นอกจากนี้ยังปรับปรุงการจัดตำแหน่งซึ่งทำให้การทำงานของหน่วยความจำ SSE เร็วขึ้น


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