3 คะแนน โดย GN⁺ 3 시간 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • เครื่องมือทดแทน Tiktoken และ HuggingFace Tokenizers ที่รองรับ CPU หลากหลายและโทเคไนเซอร์ยอดนิยม โดยประมวลผลข้อความได้ในระดับ GB/s
  • ปรับแต่ง SIMD สำหรับการทำ pre-tokenization ที่เดิมเป็นหน้าที่ของเอนจิน regex ลดการแตกแขนง การสื่อสารระหว่างเธรด และการโต้ตอบกับ Python พร้อมแคชการแมปโทเค็นของคำที่เคยพบอย่างมีประสิทธิภาพ
  • ในเบนช์มาร์ก OpenWebText ขนาด 11.9GB ปริมาณงานของ GPT-2 อยู่ที่ 24.53GB/s บน AMD EPYC 9565, 8.79GB/s บน Apple M4 Max และ 6.27GB/s บน Ryzen 7 9800X3D
  • โหมดเข้ากันได้กับ HuggingFace และ Tiktoken ช่วยให้คงโค้ดเดิมไว้ได้เกือบทั้งหมด แต่ประสิทธิภาพลดลงจากต้นทุนในการทำให้ผลลัพธ์ตรงกัน ขณะที่ Gigatoken API ซึ่งให้ Rust อ่านไฟล์โดยตรงมอบการทำงานแบบขนานสูงสุดและความเร็วสูงสุด
  • ยังไม่รองรับ WordPiece และการส่งออกเป็นไฟล์ อีกทั้งการปรับแต่ง SentencePiece และการตรวจสอบบน Windows ยังมีไม่มาก จึงเหมาะกับ BPE tokenizer และสภาพแวดล้อม Linux·macOS หรือ WSL มากกว่าในตอนนี้

ขอบเขตการรองรับและวิธีใช้งาน

  • Gigatoken เป็นโทเคไนเซอร์ความเร็วสูงสำหรับโมเดลภาษา โดยมุ่งรองรับ CPU x86·ARM สมัยใหม่และโทเคไนเซอร์ทั่วไปแทบทั้งหมด
  • ติดตั้งด้วย pip install gigatoken และมีทั้ง API ของตัวเองกับ โหมดเข้ากันได้ กับ HuggingFace Tokenizers และ Tiktoken
  • โหมดเข้ากันได้จะห่อโทเคไนเซอร์เดิม แล้วแปลงด้วย .as_hf() หรือ .as_tiktoken() ตามลำดับ
    • มีการทำงานค่อนข้างมากเพื่อให้ผลลัพธ์ตรงกับ HuggingFace Tokenizers อย่างแม่นยำ
    • การจัดการความเข้ากันได้มีต้นทุนด้านประสิทธิภาพที่มองข้ามได้ยาก จึงไม่ถึงระดับเร่งความเร็วราว 1,000 เท่าของ API ตัวเอง แต่โดยรวมยังเร็วกว่า implementation เดิม
  • API ของตัวเองรับชื่อโมเดล HuggingFace เช่น "Qwen/Qwen3-8B" และ TextFileSource แล้วเข้ารหัสไฟล์โดยตรง
    • implementation ใน Rust อ่านข้อมูลโดยตรง ข้าม overhead ที่ไม่จำเป็น และเพิ่มการทำงานแบบขนานให้สูงสุด
    • หากส่งโครงสร้างข้อมูลของ Python เข้าไป ก็ยังมีต้นทุนจากการอ่านข้อมูลใน Python อยู่

implementation ที่เพิ่มความเร็ว

  • การปรับปรุงที่ใหญ่ที่สุดมักมาจากการยกระดับ pre-tokenization ซึ่งปกติให้เอนจิน regex จัดการ ให้ทำเองบนพื้นฐาน SIMD
  • ลดการแตกแขนงให้เหลือน้อยที่สุด และปรับแต่ง แคชการแมป pre-token เป็นโทเค็น ที่ใช้ค้นหาโทเค็นเข้ารหัสของคำที่เคยพบแล้วอย่างจริงจัง
    • แคชโตเร็วและการกระจายของ pre-token มีลักษณะ long-tail จึงจัดการได้ยาก
  • ได้ประสิทธิภาพเพิ่มจากการลดการโต้ตอบกับ Python และการสื่อสารระหว่างเธรด
  • ไม่ใช่ implementation ที่ปรับเพื่อ CPU หรือโทเคไนเซอร์ตัวใดตัวหนึ่งโดยเฉพาะ แต่ปรับแต่งแยกตามชุดผสมของ CPU x86·ARM สมัยใหม่กับโทเคไนเซอร์หลายแบบ และผลลัพธ์ก็สม่ำเสมอครอบคลุมทั้ง CPU และโทเคไนเซอร์

เบนช์มาร์ก OpenWebText ขนาด 11.9GB

  • ในสภาพแวดล้อม AMD EPYC 9565 144 คอร์ ปริมาณงานของ GPT-2 อยู่ที่ 24.53GB/s เร็วกว่า HuggingFace Tokenizers ที่ 24.8MB/s อยู่ 989 เท่า และเร็วกว่า Tiktoken ที่ 36.0MB/s อยู่ 681 เท่า
    • ตระกูล BPE หลักโดยทั่วไปทำได้ราว 15.49~24.00GB/s
    • รายการที่อิง SentencePiece ช้ากว่าโดยเปรียบเทียบ อยู่ที่ราว 2.51~4.82GB/s
  • บน Apple M4 Max 16 คอร์ GPT-2 ทำได้ 8.79GB/s เร็วกว่า HuggingFace 1,268 เท่า และเร็วกว่า Tiktoken 140 เท่า
    • OLMo 2/3 เร็วกว่า HuggingFace 1,299 เท่า และ Qwen 2/2.5 เร็วกว่า 1,105 เท่า
  • บน AMD Ryzen 7 9800X3D 16 คอร์ GPT-2 ทำได้ 6.27GB/s เร็วกว่า HuggingFace 106 เท่า และเร็วกว่า Tiktoken 68 เท่า
    • ตระกูล BPE หลักอยู่ที่ราว 4.21~6.09GB/s ส่วนตระกูลที่ยังปรับแต่งน้อยกว่าโดยเปรียบเทียบอยู่ที่ราว 1.12~2.84GB/s

เงื่อนไขการวัดและการตีความ

  • OWT(OpenWebText) ถูกเลือกเป็นข้อมูลเบนช์มาร์กเพราะเป็นตัวแทนคร่าว ๆ ของข้อความที่ได้หลังดึงเอกสารจาก Common Crawl
  • Gigatoken ประมวลผลโดยไม่แบ่งไฟล์ทั้งหมดไว้ล่วงหน้า จึงทำทั้ง การค้นหาขอบเขตการแบ่งและการทำ parallelization อัตโนมัติ เอง
  • ตัวเปรียบเทียบประมวลผลข้อมูลที่แบ่งไว้ล่วงหน้าตาม <|endoftext|>
    • HuggingFace encode_batch_fast ใช้ 100MB แรก
    • Tiktoken encode_ordinary_batch ใช้ 1GB แรก
    • ทั้งสอง implementation ไม่มีการแคช ทำให้ความเร็วระหว่างประมวลผลค่อนข้างคงที่ จึงใช้เงื่อนไขเปรียบเทียบนี้
  • ผลลัพธ์ของ Tiktoken รวมเฉพาะโทเคไนเซอร์ที่รองรับอย่างเป็นทางการเท่านั้น
  • แต่ละแถวแทนโทเคไนเซอร์เฉพาะหนึ่งตัวที่มี vocab, merge และ pre-tokenizer เหมือนกัน
    • รุ่นและโมเดลแตกแขนงหลายเวอร์ชันในตระกูล Llama, Qwen, DeepSeek, GLM, Nemotron, Kimi, Phi, Gemma ถูกจัดรวมไว้ในแถวโทเคไนเซอร์เดียวกัน
  • รายการที่ช้าที่สุดคือ โทเคไนเซอร์ที่อิง SentencePiece ซึ่งใน Gigatoken ยังไม่ได้รับการปรับแต่งเพียงพอ

การตรวจสอบการรองรับและการประมวลผลขนาดใหญ่

  • สามารถตรวจสอบการทำโทเคไนซ์ของ repository โมเดล HuggingFace และวัดเวลาได้โดยไม่ต้องติดตั้ง ด้วยคำสั่ง uvx --with tokenizers gigatoken bench
  • ในตัวอย่างการตรวจสอบ GPT-2 ผลลัพธ์ของ 20,401 เอกสาร ตรงกัน
    • บน Apple M4 Max ประมวลผล 11,920.51MB ใน 1.432 วินาที ที่ 8,327.05MB/s เร็วกว่า HuggingFace 1,353.13 เท่า
    • บน AMD EPYC 9565 ประมวลผลข้อมูลเดียวกันใน 0.486 วินาที ที่ 24,532.45MB/s เร็วกว่า 989.21 เท่า
  • หากใช้อัตราประมวลผลของ EPYC จะสามารถทำโทเคไนซ์ Common Crawl ทั้งหมดขนาด 130 ล้านล้านโทเค็นได้ภายในไม่ถึง 6.5 ชั่วโมง
  • ตัวอย่างใช้ Stanford CS336 OWT sample และโดยค่าเริ่มต้น CLI ใช้ 100MB แรกของไฟล์สำหรับการตรวจสอบและเปรียบเทียบกับ HuggingFace
  • การรันครั้งแรกบน macOS อาจทำให้โค้ด Rust ช้าลงเพราะการตรวจสอบความปลอดภัย ดังนั้นเพื่อการวัดที่แม่นยำอาจต้องรันคำสั่งสองครั้ง
  • ขอให้รายงานกรณีผลลัพธ์ไม่ตรงกันหรือกรณีที่ช้าไปยัง GitHub Issue

ข้อจำกัดที่ทราบ

  • การวนซ้ำของ Python ทำใน Rust แต่ใช้ ABI3 ซึ่งช้ากว่า API เฉพาะตามเวอร์ชัน CPython ภายใน
    • มีแผนทำการปรับเฉพาะตามเวอร์ชัน Python และในการทดลองช่วงต้น กรณีที่ overhead เป็นตัวครอบงำเร็วขึ้น 2 เท่า
  • Gigatoken API ยังไม่มีการ implement file output sink
  • ไม่รองรับ WordPiece
  • การทำโทเคไนซ์ที่อิง SentencePiece มีระดับการปรับแต่งต่ำกว่า BPE ทั่วไป
    • ปัจจุบันลำดับความสำคัญยังต่ำ เพราะส่วนใหญ่ใช้โดยโมเดลของ Google และตระกูล BERT
  • การทดสอบบน Windows ยังไม่เพียงพอ จึงแนะนำให้ ใช้ WSL ในตอนนี้

ขอบเขตการใช้ AI

  • โค้ดเบสส่วนใหญ่เขียนเองโดยไม่ใช้ AI และตรวจสอบได้จากประวัติ Git ของโปรเจกต์
  • ในช่วงท้ายของโปรเจกต์ มีการใช้ AI กับงานต่อไปนี้
    • implementation ของ API สำหรับผู้ใช้
    • การทำให้ pre-tokenizer เป็นแบบทั่วไปและพอร์ตไปยังโทเคไนเซอร์เพิ่มเติม รวมถึงขยายความเข้ากันได้
    • รองรับ padding, truncation และ Unicode normalization
    • การพอร์ตกลยุทธ์ SIMD ระหว่าง AVX512·AVX2·NEON
    • การเพิ่มประสิทธิภาพช่วงสุดท้ายราว 4 เท่า ผ่านการลบการแตกแขนงและปรับปรุงลำดับชั้นของแคช pre-token
    • การ refactor และปรับปรุงการใช้โค้ดซ้ำ

1 ความคิดเห็น

 
GN⁺ 3 시간 전
ความคิดเห็นจาก Hacker News
  • คำกล่าวที่ว่า “โค้ดส่วนใหญ่เขียนเองโดยไม่ใช้ AI และตรวจสอบได้จากประวัติ Git” ทำให้คำประกาศว่า การเขียนโปรแกรมโดยมนุษย์จบแล้ว ดูจืดไปเลย

  • นี่ไม่ใช่การปรับแต่งเกินพอดีเฉพาะ CPU รุ่นใดรุ่นหนึ่งกับโทเคไนเซอร์ตัวเดียว แต่เป็นการปรับแต่งแบบครอบคลุม ชุดผสมของ x86·ARM รุ่นใหม่กับโทเคไนเซอร์หลายตัว เพื่อให้ได้ประสิทธิภาพที่สม่ำเสมอ
    โดยปรับแต่งขั้นตอน pre-tokenization ที่ปกติมักปล่อยให้ regex engine ทำ ให้ทำด้วย SIMD เองและลด branch ให้น้อยที่สุด อีกทั้งยังปรับปรุงแคช mapping ของโทเคนล่วงหน้าเพื่อให้ค้นหาผลการเข้ารหัสของคำที่เคยเห็นแล้วได้อย่างรวดเร็ว แคชในสาขานี้โตเร็วและมีหางของการกระจายยาว จึงจัดการได้ยาก
    นอกจากนี้ยังลดการโต้ตอบกับ Python และการสื่อสารระหว่างเธรดให้น้อยที่สุด

  • ทำให้นึกถึง simdjson ที่ทำความเร็วได้อย่างไม่น่าเชื่อด้วยการเขียนโปรแกรมอย่างสร้างสรรค์ ถ้าแพร่หลายก็น่าจะลดพลังงาน ต้นทุน และการปล่อยคาร์บอนได้มาก จึงอยากให้ปล่อย Rust crate ด้วย และถ้าจำเป็นก็อยากช่วยเอง

    • แทบไม่เคยมีกรณีที่ tokenization เป็นคอขวดสำคัญ และ JSON serialization ก็โดยมากเช่นกัน ใช้พลังงานไปกับ I/O และสตอเรจมากกว่า serialization และ tokenization มาก
      ถ้าคำนึงถึงเศรษฐศาสตร์และสิ่งแวดล้อม การประมวลผลคำขอแบบ batch ให้ผลมากกว่า ปัญหาที่แพงที่สุดคืออัตราการใช้งาน GPU ต่ำ และถ้าปรับงานให้เข้ากับรูปแบบ batch ปัจจุบันที่ OAI ก็ประหยัดได้ 50% หากไม่จำเป็นต้องได้ทุกคำตอบทันที บางส่วนรอได้เป็นวัน การเรียกใช้เครื่องมือก็ไม่ timeout และตัว LLM เองไม่มีเวลาแบบ wall-clock
  • ลองโคลน repository มาดูแล้ว แนวทาง แทนที่ regex สำหรับ pre-tokenization และการปรับแคชให้เหมาะสมมีประโยชน์โดยทั่วไปด้วย เป็นผลงานที่ยอดเยี่ยมจนทั้งชุมชน tokenization น่าจะอยากเรียนรู้เคล็ดลับของการเร่งความเร็วแบบนี้

    • เร็ว ๆ นี้จะทำ คำอธิบายเชิงเทคนิคและ论文 ของโปรเจกต์ รวมถึงวิดีโอการนำเสนอ แล้วจะแชร์ใน Discord ด้วย
    • มีคุณค่าสูงไม่ใช่แค่สำหรับ inference แต่ยังรวมถึง การฝึก ด้วยชุดข้อมูลแบบ proprietary และที่น่าประทับใจคือทั้งหมดนี้ทำโดยคนเพียงคนเดียว
  • เป็นความสำเร็จที่ยอดเยี่ยม แต่โดยปกติ tokenization คิดเป็น น้อยกว่า 0.1% ของเวลา inference ทั้งหมด อย่างไรก็ตามจะมีประโยชน์มากสำหรับแอปที่ต้องใช้ tokenization โดยตรง

    • สัดส่วนของ tokenization อาจสูงขึ้นได้มากขึ้นอยู่กับวิธี inference จากการวัดเบื้องต้นเมื่อรัน 8B Qwen3 บน B200 ตัวเดียว เมื่อเปลี่ยนมาใช้ gigatoken เวลาในการสร้างโทเคนแรก (TTFT) ลดลงโดยเฉลี่ย 5.5% ที่ความยาวอินพุต 2,048, 8.4% ที่ 8,192 และ 7.8% ที่ 32,768
      ยิ่งโมเดลเล็กหรือ GPU เร็ว ผลก็ยิ่งมากขึ้น และต้องตรวจสอบเพิ่มเติมก่อนใส่ใน README แหล่งที่มาของ benchmark คือ fastokens
    • ในแพลตฟอร์ม AI จำเป็นต้อง tokenize คำขออย่างรวดเร็วตั้งแต่ช่วงต้น เพื่อกำหนด การ route, rate limit และอื่น ๆ ในภายหลัง แม้สัดส่วนต่อเวลาคำขอทั้งหมดจะเล็ก แต่ประสิทธิภาพก็สำคัญ
    • tokenization ส่วนใหญ่เป็นงานแบบ serial ดังนั้นถ้า prompt เริ่มต้นมีขนาดใหญ่ อาจกินสัดส่วนมากในเวลาประมวลผลอินพุต เพราะหลังจากส่งต่อให้โมเดล inference แล้ว โทเคนทั้งหมดสามารถประมวลผลแบบขนานได้
    • แม้จะเป็นเพียง 1/1,000 ของงานคำนวณ inference แต่เมื่อสเกลใหญ่ขึ้นก็ละเลยได้ยาก Gartner ประเมินค่าใช้จ่าย inference ปี 2026 ไว้ราว 28 พันล้านดอลลาร์ ดังนั้นถ้าใช้สมมติฐานข้างต้น จะเท่ากับ ปีละ 28 ล้านดอลลาร์
      ที่มา: https://www.gartner.com/en/newsroom/press-releases/2026-07-2...
    • โดยเฉพาะในโมเดลขนาดเล็ก สามารถลด latency ในการสร้างโทเคนแรก ได้มาก สำหรับผู้ให้บริการ inference อย่าง Groq หรือ Cerebras latency สำคัญพอ ๆ กับ throughput รวม
  • ดูเหมือนจะมีประโยชน์กว่าในขั้นตอน เตรียมข้อมูล pre-training แบบออฟไลน์ มากกว่าตอน inference ช่วยประหยัดเวลาและต้นทุนเมื่อต้อง tokenize ข้อความหลายเทราไบต์สำหรับคลังข้อมูลฝึก และลดรอบการทำซ้ำในการปรับชุดข้อมูลได้ด้วย

  • การทุ่มความสามารถด้านวิศวกรรมเพื่อทำให้ส่วนที่กินเวลา 0.1% ของเวลารันทั้งหมด เร็วขึ้น 1,000 เท่า นี่แหละคือพฤติกรรมที่สมกับเป็นนักพัฒนาซอฟต์แวร์ที่สุด

    • เคยทำ word cloud ความละเอียดสูงด้วย Rust ได้ในราว 100ms และปรับเพิ่มจนเหลือประมาณ 16ms โลกไม่ได้ต้องการเครื่องสร้าง word cloud ที่เร็วขนาดนี้หรอก แต่ถ้าจะทำแล้ว ก็ควรเร็วที่สุดเท่าที่เป็นไปได้
    • การแสวงหาความเป็นเลิศ ไม่จำเป็นต้องมีเหตุผลรองรับ”
      https://x.com/mitchellh/status/2074225453217505494
    • ขึ้นอยู่กับ workflow ยังมีการใช้งานที่ ทำแค่ tokenization โดยไม่ได้ป้อนข้อความเข้าโมเดลทันทีด้วย
    • ต่อให้เป็นองค์ประกอบย่อย หาก ปรับปรุงได้ 1,000 เท่า ก็อาจเปิดทางให้ฟีเจอร์ใหม่ในเชิงคุณภาพได้ เหตุผลที่ส่วนนั้นเป็นแค่ 0.1% ของทั้งหมดก็มักเป็นผลจากทัศนคติที่ซ้ำไปซ้ำมาทั่วทั้งโปรเจกต์ว่า “ไม่มีผลต่อประสิทธิภาพรวม แล้วจะทำให้ดีไปทำไม”
      LLM ใกล้เพดานการปรับปรุง 1,000 เท่ามากกว่าเยอะก็จริง แต่แม้แต่ operation พื้นฐานใน PyTorch ก็มักช้ากว่าการเขียนใหม่แบบง่าย ๆ 2 เท่า และอัลกอริทึม scheduling ที่ดีกว่าก็ให้ผลดีขึ้น 5–10 เท่าได้ tokenization ที่เร็วอาจเปิดฟังก์ชันอื่นที่เคยมองข้ามเพราะก่อนหน้านี้ทำไม่ได้จริง
    • ถ้าทำ tokenization เพื่อรันโมเดลภาษาขนาดเล็กมาก (SLM) สำหรับ routing สัดส่วนอาจสูงกว่า 0.1% มาก นี่เป็นแนวคิดแบบเดียวกับ “พีซีส่วนใหญ่ว่างอยู่ที่เดสก์ท็อป ดังนั้นการปรับแต่งไดรเวอร์ GPU ไม่สำคัญ”
  • เป็น ประสิทธิภาพที่ไม่น่าเชื่อ จนต้องจ้องกราฟอยู่นานเพื่อทำความเข้าใจตัวเลข

  • นี่เป็นฟีเจอร์ที่ ClickHouse ต้องการพอดี จึงจะลองทดสอบที่ https://github.com/ClickHouse/ClickHouse/issues/108247
    ถ้า README เน้น ประสิทธิภาพต่อคอร์ มากขึ้นก็น่าจะดี และสงสัยว่าในอัลกอริทึมจริง การ matching ด้วย hash table แบบสมบูรณ์จะช่วยได้หรือไม่

  • ถ้าอย่างนั้นก็น่าสงสัยว่าในส่วนอื่น ๆ ของ pipeline inference ยังเหลือโอกาส ปรับให้เร็วขึ้น 1,000 เท่า อีกมากแค่ไหน

    • ต่างจากชั้น tokenization การเปลี่ยนแปลงอื่น ๆ ใน inference ตัดสินได้ยากว่าแม่นยำถูกต้องหรือไม่
    • มีส่วนแบบนั้นอยู่มาก และแทบทุกองค์ประกอบก็มีทีมเฉพาะกับงานวิจัยรองรับอยู่แล้ว มีความเป็นไปได้สูงว่าจะมี breakthrough ใหญ่ ๆ อีกหลายครั้งในอนาคต
    • ส่วนที่กินสัดส่วนเวลาของ inference มากกว่าน่าจะได้รับความพยายามปรับแต่งมากกว่านี้ไปแล้ว