Rust ile İşletim Sistemi Yazıyoruz

Philipp Oppermann's blog

SIMD'yi Devre Dışı Bırakmak

Single Instruction Multiple Data (SIMD) komutları, bir işlemi (örneğin toplama) aynı anda birden çok veri sözcüğü üzerinde gerçekleştirebilir; bu da programları önemli ölçüde hızlandırabilir. x86_64 mimarisi çeşitli SIMD standartlarını destekler:

  • MMX: Multi Media Extension komut kümesi 1997’de tanıtıldı ve mm0’dan mm7’ye kadar adlandırılan sekiz adet 64-bit register tanımlar. Bu register’lar yalnızca x87 kayan nokta birimi (floating point unit) register’larının takma adlarıdır.
  • SSE: Streaming SIMD Extensions komut kümesi 1999’da tanıtıldı. Kayan nokta register’larını yeniden kullanmak yerine, tamamen yeni bir register kümesi ekler. xmm0’dan xmm15’e kadar adlandırılan on altı yeni register vardır ve her biri 128 bittir.
  • AVX: Advanced Vector Extensions, multimedya register’larının boyutunu daha da artıran uzantılardır. Yeni register’lar ymm0’dan ymm15’e kadar adlandırılır ve her biri 256 bittir. xmm register’larını genişletirler, böylece örneğin xmm0, ymm0’ın alt yarısıdır.

Bu tür SIMD standartlarını kullanarak programlar genellikle önemli ölçüde hızlanabilir. İyi derleyiciler, otomatik vektörleştirme (auto-vectorization) adı verilen bir süreç aracılığıyla normal döngüleri otomatik olarak bu tür SIMD koduna dönüştürebilir.

Ancak büyük SIMD register’ları, OS kernel’lerinde sorunlara yol açar. Bunun nedeni, kernel’in her donanım interrupt’ında kullandığı tüm register’ları belleğe yedeklemesi gerektiğidir; çünkü kesintiye uğramış program devam ettiğinde bunların orijinal değerlerine sahip olması gerekir. Yani kernel SIMD register’larını kullanırsa, çok daha fazla veriyi (512–1600 bayt) yedeklemesi gerekir ve bu da performansı gözle görülür biçimde düşürür. Bu performans kaybını önlemek için sse ve mmx özelliklerini devre dışı bırakmak istiyoruz (avx özelliği zaten varsayılan olarak devre dışıdır).

Bunu, hedef belirtimimizdeki features alanı aracılığıyla yapabiliriz. mmx ve sse özelliklerini devre dışı bırakmak için, onları önlerine eksi koyarak ekliyoruz:

"features": "-mmx,-sse"

Kayan Nokta (Floating Point)

Bizim için ne yazık ki, x86_64 mimarisi kayan nokta işlemleri için SSE register’larını kullanır. Dolayısıyla, SSE devre dışıyken kayan noktanın her kullanımı LLVM’de bir hataya neden olur. Sorun, Rust’ın core kütüphanesinin zaten float’ları kullanmasıdır (örneğin f32 ve f64 için trait’ler uygular), bu yüzden kernel’imizde float’lardan kaçınmak yeterli değildir.

Neyse ki LLVM, tüm kayan nokta işlemlerini normal tamsayılara dayalı yazılım fonksiyonları aracılığıyla öykünen bir soft-float özelliğine destek sağlar. Bu, kernel’imizde SSE olmadan float kullanmayı mümkün kılar; sadece biraz daha yavaş olur.

Kernel’imiz için soft-float özelliğini açmak amacıyla, onu hedef belirtimimizdeki features satırına önüne artı koyarak ekliyoruz:

"features": "-mmx,-sse,+soft-float"

Comments

Bir sorunuz mu var, geri bildirim paylaşmak veya fikirlerinizi tartışmak mı istiyorsunuz? Buraya yorum bırakmaktan çekinmeyin! Lütfen İngilizce kullanın ve Rust'ın davranış kurallarına uyun. Bu yorum dizisi doğrudan GitHub'daki bir tartışmaya bağlıdır, dolayısıyla isterseniz oraya da yorum yapabilirsiniz.

Instead of authenticating the giscus application, you can also comment directly on GitHub.