แนวทางปฏิบัติที่ดีที่สุดในการทดสอบ TensorFlow

แนวทางปฏิบัติที่แนะนำสำหรับการทดสอบโค้ดใน พื้นที่เก็บข้อมูล TensorFlow มีดังนี้

ก่อนที่คุณจะเริ่มต้น

ก่อนที่คุณจะสนับสนุนซอร์สโค้ดให้กับโปรเจ็กต์ TensorFlow โปรดตรวจสอบไฟล์ CONTRIBUTING.md ในที่เก็บ GitHub ของโปรเจ็กต์ (ตัวอย่างเช่น ดู ไฟล์ CONTRIBUTING.md สำหรับ repo TensorFlow หลัก ) ผู้ร่วมเขียนโค้ดทุกคนจะต้องลงนามใน ข้อตกลงใบอนุญาตผู้ร่วมให้ข้อมูล (CLA)

หลักการทั่วไป

ขึ้นอยู่กับสิ่งที่คุณใช้ในกฎ BUILD ของคุณเท่านั้น

TensorFlow เป็นไลบรารีขนาดใหญ่ และขึ้นอยู่กับแพ็คเกจเต็มเมื่อเขียน Unit Test สำหรับโมดูลย่อยถือเป็นแนวทางปฏิบัติทั่วไป อย่างไรก็ตาม การดำเนินการนี้จะปิดใช้งานการวิเคราะห์ตามการพึ่งพา bazel ซึ่งหมายความว่าระบบบูรณาการอย่างต่อเนื่องไม่สามารถกำจัดการทดสอบที่ไม่เกี่ยวข้องสำหรับการดำเนินการก่อนส่ง/หลังส่งได้อย่างชาญฉลาด หากคุณพึ่งพาเฉพาะโมดูลย่อยที่คุณกำลังทดสอบในไฟล์ BUILD ของคุณ คุณจะประหยัดเวลาสำหรับนักพัฒนา TensorFlow ทั้งหมด และพลังการคำนวณอันมีค่ามากมาย

อย่างไรก็ตาม การแก้ไขการพึ่งพาบิวด์ของคุณเพื่อละเว้นเป้าหมาย TF แบบเต็มทำให้เกิดข้อจำกัดบางประการสำหรับสิ่งที่คุณสามารถนำเข้าในโค้ด Python ของคุณได้ คุณจะไม่สามารถใช้ import tensorflow as tf ในการทดสอบหน่วยของคุณได้อีกต่อไป แต่นี่เป็นการแลกเปลี่ยนที่คุ้มค่า เนื่องจากช่วยให้นักพัฒนาทุกคนไม่ต้องทำการทดสอบที่ไม่จำเป็นนับพันครั้ง

รหัสทั้งหมดควรมีการทดสอบหน่วย

สำหรับโค้ดใดๆ ที่คุณเขียน คุณควรเขียน Unit Tests ด้วย หากคุณเขียนไฟล์ใหม่ foo.py คุณควรวาง unit tests ใน foo_test.py และส่งภายในการเปลี่ยนแปลงเดียวกัน ตั้งเป้าให้ครอบคลุมการทดสอบเพิ่มขึ้น >90% สำหรับโค้ดทั้งหมดของคุณ

หลีกเลี่ยงการใช้กฎการทดสอบ bazel ดั้งเดิมใน TF

TF มีรายละเอียดปลีกย่อยมากมายเมื่อทำการทดสอบ เราได้ทำงานเพื่อซ่อนความซับซ้อนเหล่านั้นทั้งหมดในมาโคร Bazel ของเรา เพื่อหลีกเลี่ยงการจัดการกับสิ่งเหล่านั้น ให้ใช้สิ่งต่อไปนี้แทนกฎการทดสอบดั้งเดิม โปรดทราบว่าสิ่งเหล่านี้ทั้งหมดถูกกำหนดไว้ใน tensorflow/tensorflow.bzl สำหรับการทดสอบ CC ให้ใช้ tf_cc_test , tf_gpu_cc_test , tf_gpu_only_cc_test สำหรับการทดสอบหลาม ให้ใช้ tf_py_test หรือ gpu_py_test หากคุณต้องการบางสิ่งที่ใกล้เคียงกับกฎ py_test ดั้งเดิมมาก โปรดใช้กฎที่กำหนดไว้ใน tensorflow.bzl แทน คุณเพียงแค่ต้องเพิ่มบรรทัดต่อไปนี้ที่ด้านบนของไฟล์ BUILD: load(“tensorflow/tensorflow.bzl”, “py_test”)

โปรดทราบว่าการทดสอบจะดำเนินการที่ไหน

เมื่อคุณเขียนการทดสอบ อินฟราทดสอบของเราจะดูแลการทดสอบของคุณบน CPU, GPU และตัวเร่งความเร็ว หากคุณเขียนการทดสอบเหล่านั้นตามนั้น เรามีการทดสอบอัตโนมัติที่ทำงานบน Linux, MacOS, Windows ซึ่งมีระบบที่มีหรือไม่มี GPU คุณเพียงแค่ต้องเลือกมาโครตัวใดตัวหนึ่งที่แสดงไว้ด้านบน จากนั้นใช้แท็กเพื่อจำกัดตำแหน่งที่จะดำเนินการ

  • แท็ก manual จะแยกการทดสอบของคุณไม่ให้ทำงานที่ใดก็ได้ ซึ่งรวมถึงการดำเนินการทดสอบด้วยตนเองที่ใช้รูปแบบ เช่น bazel test tensorflow/…

  • no_oss จะยกเว้นการทดสอบของคุณไม่ให้ทำงานในโครงสร้างพื้นฐานการทดสอบ TF OSS อย่างเป็นทางการ

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

  • แท็ก no_gpu สามารถใช้เพื่อแยกการทดสอบของคุณไม่ให้ทำงานในชุดการทดสอบ GPU

ตรวจสอบการทดสอบที่ทำงานในชุดการทดสอบที่คาดไว้

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

  • รอให้การส่งคำขอดึงล่วงหน้า (PR) ของคุณดำเนินการให้เสร็จสิ้น
  • เลื่อนไปที่ด้านล่างของ PR ของคุณเพื่อดูการตรวจสอบสถานะ
  • คลิกลิงก์ "รายละเอียด" ที่ด้านขวาของเช็ค Kokoro
  • ตรวจสอบรายการ "เป้าหมาย" เพื่อค้นหาเป้าหมายที่เพิ่มใหม่ของคุณ

แต่ละชั้นเรียน/หน่วยควรมีไฟล์ทดสอบหน่วยของตนเอง

ชั้นเรียนการทดสอบที่แยกจากกันช่วยให้เราแยกความล้มเหลวและทรัพยากรได้ดีขึ้น ทำให้ไฟล์ทดสอบสั้นลงและอ่านง่ายขึ้นมาก ดังนั้น ไฟล์ Python ทั้งหมดของคุณควรมีไฟล์ทดสอบที่เกี่ยวข้องอย่างน้อยหนึ่งไฟล์ (สำหรับแต่ละ foo.py ควรมี foo_test.py ) สำหรับการทดสอบที่ซับซ้อนมากขึ้น เช่น การทดสอบการรวมที่ต้องมีการตั้งค่าที่แตกต่างกัน คุณสามารถเพิ่มไฟล์ทดสอบเพิ่มเติมได้

ความเร็วและระยะเวลาการทำงาน

ควรใช้เศษให้น้อยที่สุด

แทนที่จะแบ่งย่อย โปรดพิจารณา:

  • ทำให้การทดสอบของคุณเล็กลง
  • หากไม่สามารถทำได้ข้างต้น ให้แยกการทดสอบออก

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

การทดสอบขนาดเล็กจะดีกว่า

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

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

เวลาทดสอบควรมุ่งเป้าไปที่ครึ่งหนึ่งของระยะหมดเวลาของขนาดการทดสอบเพื่อหลีกเลี่ยงการสะเก็ด

ด้วยเป้าหมายการทดสอบ bazel การทดสอบขนาดเล็กจะมีระยะหมดเวลา 1 นาที ระยะหมดเวลาการทดสอบปานกลางคือ 5 นาที การทดสอบขนาดใหญ่ไม่ได้ดำเนินการโดยอินฟราการทดสอบ TensorFlow อย่างไรก็ตาม การทดสอบจำนวนมากไม่สามารถกำหนดระยะเวลาได้ ด้วยเหตุผลหลายประการ การทดสอบของคุณอาจใช้เวลานานขึ้นเป็นครั้งคราว และหากคุณทำเครื่องหมายการทดสอบที่ทำงานเป็นเวลา 50 วินาทีโดยเฉลี่ยว่ามีขนาดเล็ก การทดสอบของคุณจะหลุดออกหากจัดกำหนดการบนเครื่องที่มี CPU เก่า ดังนั้นให้ตั้งเป้าเวลาทำงานเฉลี่ย 30 วินาทีสำหรับการทดสอบเล็กๆ น้อยๆ ตั้งเป้าไว้ที่ 2 นาที 30 วินาทีของเวลาวิ่งโดยเฉลี่ยสำหรับการทดสอบระดับกลาง

ลดจำนวนตัวอย่างและเพิ่มเกณฑ์ความคลาดเคลื่อนในการฝึกอบรม

การทดสอบที่ทำงานช้าจะขัดขวางผู้มีส่วนร่วม การฝึกซ้อมในการทดสอบอาจทำได้ช้ามาก ต้องการความคลาดเคลื่อนที่สูงขึ้นเพื่อให้สามารถใช้ตัวอย่างน้อยลงในการทดสอบของคุณ เพื่อให้การทดสอบของคุณรวดเร็วเพียงพอ (สูงสุด 2.5 นาที)

ขจัดความไม่แน่นอนและสะเก็ด

เขียนแบบทดสอบเชิงกำหนด

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

ทำการสุ่มแหล่งที่มาของการสุ่มเสมอ

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

# Python RNG
import random
random.seed(42)

# Numpy RNG
import numpy as np
np.random.seed(42)

# TF RNG
from tensorflow.python.framework import random_seed
random_seed.set_seed(42)

หลีกเลี่ยงการใช้ sleep ในการทดสอบแบบมัลติเธรด

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

ตรวจสอบว่าการทดสอบเป็นขุยหรือไม่

Flakes ทำให้ buildcops และนักพัฒนาเสียเวลาหลายชั่วโมง ตรวจพบได้ยากและแก้ไขจุดบกพร่องได้ยาก แม้ว่าจะมีระบบอัตโนมัติในการตรวจจับความไม่แน่นอน แต่ก็จำเป็นต้องสะสมการทดสอบหลายร้อยครั้งก่อนจึงจะสามารถปฏิเสธการทดสอบได้อย่างแม่นยำ แม้ว่าพวกเขาจะตรวจพบ พวกเขาปฏิเสธรายการการทดสอบของคุณ และความครอบคลุมของการทดสอบก็จะหายไป ดังนั้นผู้เขียนทดสอบควรตรวจสอบว่าการทดสอบของพวกเขาไม่สม่ำเสมอหรือไม่เมื่อเขียนแบบทดสอบ ซึ่งสามารถทำได้ง่ายๆ ด้วยการรันการทดสอบด้วยแฟล็ก: --runs_per_test=1000

ใช้ TensorFlowTestCase

TensorFlowTestCase ใช้ความระมัดระวังที่จำเป็น เช่น การเพาะตัวสร้างตัวเลขสุ่มทั้งหมดที่ใช้เพื่อลดความไม่สม่ำเสมอให้มากที่สุด ขณะที่เราค้นพบและแก้ไขแหล่งที่มาของความไม่สม่ำเสมอเพิ่มเติม สิ่งเหล่านี้ทั้งหมดจะถูกเพิ่มลงใน TensorFlowTestCase ดังนั้น คุณควรใช้ TensorFlowTestCase เมื่อเขียนการทดสอบสำหรับ tensorflow TensorFlowTestCase ถูกกำหนดไว้ที่นี่: tensorflow/python/framework/test_util.py

เขียนการทดสอบสุญญากาศ

การทดสอบสุญญากาศไม่จำเป็นต้องใช้ทรัพยากรภายนอก พวกเขาเต็มไปด้วยทุกสิ่งที่พวกเขาต้องการ และพวกเขาเพิ่งเริ่มให้บริการปลอมๆ ที่พวกเขาต้องการ บริการใดๆ นอกเหนือจากการทดสอบของคุณถือเป็นแหล่งที่มาของสิ่งที่ไม่ได้กำหนดไว้ แม้ว่าบริการอื่นๆ จะมีความพร้อมใช้งานถึง 99% แต่เครือข่ายก็อาจเกิดข้อผิดพลาดได้ การตอบสนองของ rpc อาจล่าช้าได้ และคุณอาจได้รับข้อความแสดงข้อผิดพลาดที่อธิบายไม่ได้ บริการภายนอกอาจเป็นแต่ไม่จำกัดเพียง GCS, S3 หรือเว็บไซต์ใดๆ