ตัวประมวลผลที่มีประสิทธิภาพสูงกว่าตัวกรองพิกเซลสำหรับการกรองภาพเมื่อใด


37

การดำเนินการกรองภาพเช่น blurs, SSAO, บลูมและอื่น ๆ มักจะทำโดยใช้ shaders พิกเซลและการดำเนินการ "รวบรวม" โดยที่การเรียกพิกเซล shader แต่ละครั้งจะมีปัญหาจำนวนเนื้อเรียกเพื่อเข้าถึงค่าพิกเซลที่อยู่ใกล้เคียงและคำนวณมูลค่าพิกเซลเดียว ผลลัพธ์. วิธีการนี้มีความไร้ประสิทธิภาพทางทฤษฎีในการดึงข้อมูลซ้ำซ้อนจำนวนมาก: การเรียกใช้ shader ที่อยู่ใกล้เคียงจะดึงข้อความเดียวกันซ้ำหลาย ๆ ข้อความ

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

คำถามอยู่ภายใต้สถานการณ์ใด (ถ้าเคย) เป็นวิธีการคำนวณ - shader จริงเร็วกว่าวิธีพิกเซล -shader? มันขึ้นอยู่กับขนาดของเคอร์เนลการดำเนินการกรองแบบไหน ฯลฯ เห็นได้ชัดว่าคำตอบจะแตกต่างจาก GPU รุ่นหนึ่งไปยังอีกรุ่นหนึ่ง แต่ฉันสนใจที่จะได้ยินหากมีแนวโน้มทั่วไป


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

@bernie คุณสามารถชี้แจงสิ่งที่จำเป็นสำหรับการคำนวณ shader ที่จะ "ทำอย่างถูกต้อง"? อาจจะเขียนคำตอบ? ดีเสมอที่จะได้รับมุมมองเพิ่มเติมเกี่ยวกับเรื่อง :)
นาธานรีด

2
ตอนนี้ดูสิ่งที่คุณทำให้ฉันทำ! :)
bernie

นอกเหนือจากการแบ่งปันงานข้ามเธรดความสามารถในการใช้ async compute เป็นอีกหนึ่งเหตุผลใหญ่ที่ใช้ compute shaders
JarkkoL

คำตอบ:


23

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

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

คุณอาจสามารถเปลี่ยนการบรรจุ warp / wavefront ที่เปลี่ยนเป็นประโยชน์อีกครั้งได้ แต่ถ้าคุณรู้ว่าการดำเนินการเฉพาะของคุณมีโครงสร้างย่อยที่คุณสามารถใช้ประโยชน์จากการบรรจุงานที่เกี่ยวข้องในกลุ่มเธรดเดียวกัน ในทางทฤษฎีแล้วคุณสามารถแบ่งการสุ่มตัวอย่างฮาร์ดแวร์ได้โดยการสุ่มค่าหนึ่งค่าต่อเลนและวางผลลัพธ์ในหน่วยความจำแบบแบ่งใช้สำหรับเลนอื่น ๆ เพื่อเข้าถึงโดยไม่ต้องสุ่มตัวอย่าง การชนะจะขึ้นอยู่กับว่าหน่วยความจำที่แบ่งใช้ของคุณมีราคาแพงหรือไม่: ถ้ามันถูกกว่าแคชพื้นผิวระดับต่ำสุดนี่อาจเป็นชัยชนะ แต่ไม่มีการรับประกันใด ๆ GPU นั้นจัดการได้ดีมากกับการดึงพื้นผิวในระดับสูง (ตามความจำเป็น)

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


ฉันสงสัยอย่างจริงจังว่า ROP จะเพิ่มค่าใช้จ่ายในการดำเนินการใด ๆ หากการผสมถูกปิดใช้งาน
GroverManheim

@GroverManheim ขึ้นอยู่กับสถาปัตยกรรม! เอาท์พุทการควบรวมกิจการ / ขั้นตอน ROP ยังมีการจัดการรับประกันการสั่งซื้อแม้ว่าการปิดการใช้งานการผสม ด้วยรูปสามเหลี่ยมแบบเต็มหน้าจอไม่มีอันตรายใด ๆ ในการสั่งซื้อ แต่ฮาร์ดแวร์อาจไม่ทราบ อาจมีทาง
ลัด

10

จอห์นได้เขียนคำตอบที่ดีเยี่ยมแล้วดังนั้นให้พิจารณาคำตอบนี้เป็นส่วนขยายของเขา

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

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

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

เมื่อใช้ตัวประมวลผลร่วมจะสามารถใช้ซิลิคอนใน GPU มากขึ้นในการทำงานจริง จำเป็นต้องใช้ขั้นตอนเพิ่มเติมทั้งหมดเหล่านี้เมื่อใช้เส้นทาง Pixel Shader:

  • แอสเซมบลีจุดยอด (อ่านแอตทริบิวต์จุดสุดยอด, ตัวหารจุดสุดยอด, การแปลงชนิดขยายไปสู่ ​​vec4 เป็นต้น)
  • จุดสุดยอด shader จะต้องมีการกำหนดไม่ว่ามันจะน้อยที่สุด
  • แรสเตอร์เซอร์ต้องคำนวณรายการของพิกเซลเพื่อแรเงาและแก้ไขเอาต์พุตจุดสุดยอด (อาจเป็นเพียง coords พื้นผิวสำหรับการประมวลผลภาพ)
  • ต้องตั้งค่าและจัดการสถานะที่แตกต่างกันทั้งหมด (การทดสอบเชิงลึก, การทดสอบอัลฟา, กรรไกร, การผสม)

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

สิ่งที่ผู้ขับขี่ไม่สามารถทำได้คือการหาโอกาสในการขนานที่ดีขึ้นโดยไปป์คำนวณ shader นำตัวอย่างคลาสสิกของตัวกรอง Gaussian ใช้การคำนวณเฉดสีคุณสามารถทำสิ่งนี้ (แยกตัวกรองหรือไม่):

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

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

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

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

อ้างอิง


3

ฉันสะดุดในบล็อกนี้: คำนวณการเพิ่มประสิทธิภาพ Shader สำหรับ AMD

ให้เทคนิคที่สามารถทำได้ในการคำนวณ Shader (ที่เฉพาะเจาะจงกับการคำนวณเฉดสี) ฉันอยากรู้ว่าถ้าการลดลงของการคำนวณแบบขนานนั้นเร็วกว่าการใช้พิกเซลแชดเดอร์ ฉันส่งอีเมลถึงผู้เขียน Wolf Engel เพื่อถามว่าเขาได้ลองใช้ Pixel Shader หรือไม่ เขาตอบว่าใช่และย้อนกลับไปเมื่อเขาเขียนบล็อกโพสต์เวอร์ชันของตัวคำนวณที่ใช้ในการประมวลผลนั้นเร็วกว่ารุ่นตัวสร้างพิกเซลอย่างมาก นอกจากนี้เขายังเสริมว่าวันนี้ความแตกต่างก็ยิ่งใหญ่ขึ้น ดังนั้นจึงเห็นได้ชัดว่ามีบางกรณีที่การใช้ตัวประมวลผลสามารถเป็นประโยชน์มาก

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