Hızlı tamsayı türleri neden diğer tamsayı türlerinden daha hızlıdır?


107

ISO / IEC 9899: 2018'de (C18) 7.20.1.3'te belirtilmiştir:

7.20.1.3 En hızlı minimum genişlikli tamsayı türleri

1 Aşağıdaki türlerin her biri, en az belirtilen genişliğe sahip tüm tamsayı türleri arasında çalışmak için genellikle en hızlı olan bir tamsayı türünü belirtir 268) .

2 typedef adı int_fastN_t, genişliği en az N olan en hızlı imzalı tamsayı türünü belirtir . Typedef adı , en az N genişliği olan en uint_fastN_thızlı işaretsiz tamsayı türünü belirtir.

3 Aşağıdaki türler gereklidir:

int_fast8_t, int_fast16_t, int_fast32_t, int_fast64_t, uint_fast8_t, uint_fast16_t, uint_fast32_t,uint_fast64_t

Bu formun diğer tüm türleri isteğe bağlıdır.


268) Belirlenen türün her amaç için en hızlı olduğu garanti edilmez; uygulamanın bir türü diğerine göre seçmek için net bir temeli yoksa, yalnızca imza ve genişlik gereksinimlerini karşılayan bir tamsayı türü seçecektir.


Ancak bu "hızlı" tamsayı türlerinin neden daha hızlı olduğu belirtilmemiştir.

  • Bu hızlı tamsayı türleri neden diğer tamsayı türlerinden daha hızlı?

Soruyu C ++ ile etiketledim, çünkü hızlı tamsayı türleri C ++ 17'de başlık dosyasında da mevcut cstdint. Ne yazık ki, ISO / IEC 14882: 2017'de (C ++ 17) açıklamaları hakkında böyle bir bölüm yoktur; Bu bölümü soru gövdesinde başka türlü uygulamıştım.


Bilgi: C dilinde, başlık dosyasında bildirilir stdint.h.


24
Buradaki kilit nokta, bu tamsayı türlerinin ayrı, sihirli olarak daha hızlı türler olmamasıdır. Onlar sadece bu işlem için o makinede en hızlı olan normal türün takma adlarıdır.
mtraceur

3
Derleyici, bellek konumlarını ve belirli boyutlardaki kayıtları yüklemek, depolamak, maskelemek ve değiştirmek için CPU işlem opcodesleri yayar; CPU'nun gördüğü tek şey bu. İşletim sisteminin bununla hiçbir ilgisi yoktur. Derleyicinin yaptığı gibi, sanki verilen typedef'i kendiniz belirtmişsiniz gibi. ( Bir derleyicinin, davranışta görünür bir fark olmadığı sürece, bir kullanıcı tür tanımından daha farklı bir şekilde - belki de daha verimli bir şekilde - dahili olarak işlemesine izin verildiğini varsayalım .)
Peter - Monica

1
@ RobertS-ReinstateMonica Kesin olarak, bu "takma adlar" sadece typedefifadelerdir. Yani tipik olarak , standart kütüphane düzeyinde yapılır. Onlar ne Tabii ki, C standart koyar hiçbir sınırlama typedefböylece örneğin tipik bir uygulama yapmaktır - için int_fast32_tbir typedefbir int32 bit sistemde, ama varsayımsal bir derleyici olabilir örneğin bir uygulamaya __int_fastiçsel tipi ve bazı fantezi yapmak için söz bu türdeki değişkenler için duruma göre en hızlı makine türünü seçmek için yapılan optimizasyonlar ve daha sonra kütüphane bunu yapabilir typedef.
mtraceur

1
@ RobertS-ReinstateMonica Evet, doğru. İkili dosyayı daha az taşınabilir yapan mimariye özgü derleme bayraklarıyla maksimum performans programları elde edersiniz.
Peter - Monica'yı

1
Roberts-ReinstateMonica @ En bu derlenmiş platform üzerinde etkili olacaktır için , ille ilgili .
HABO

Yanıtlar:


152

Sadece 64 bit aritmetik işlemler yapan bir CPU düşünün. Şimdi böyle bir CPU'ya imzasız bir 8 bit eklemeyi nasıl uygulayacağınızı hayal edin. Doğru sonucu elde etmek için mutlaka birden fazla işlem yapılması gerekir. Bu tür CPU'larda, 64 bit işlemler diğer tamsayı genişliklerindeki işlemlerden daha hızlıdır. Bu durumda, hepsiXint_fastY_t 64 bit türünde bir takma ad olabilir.

CPU dar tamsayı türleri için hızlı işlemleri destekliyorsa ve bu nedenle daha geniş bir tip daha dar olandan daha hızlı değilse, Xint_fastY_t tüm Y bitlerini temsil etmek için gerekenden daha geniş bir türün diğer adı olmayacaktır.

Meraktan, bazı mimarilerde belirli bir uygulamanın (GNU, Linux) boyutlarını kontrol ettim. Bunlar, aynı mimari üzerindeki tüm uygulamalarda aynı değildir:

┌────╥───────────────────────────────────────────────────────────┐
 Y     sizeof(Xint_fastY_t) * CHAR_BIT                         
    ╟────────┬─────┬───────┬─────┬────────┬──────┬────────┬─────┤
     x86-64  x86  ARM64  ARM  MIPS64  MIPS  MSP430  AVR 
╞════╬════════╪═════╪═══════╪═════╪════════╪══════╪════════╪═════╡
 8   8       8    8      32   8       8     16      8   
 16  64      32   64     32   64      32    16      16  
 32  64      32   64     32   64      32    32      32  
 64  64      64   64     64   64      64    64      64  
└────╨────────┴─────┴───────┴─────┴────────┴──────┴────────┴─────┘

Daha büyük türlerdeki işlemler daha hızlı olabilse de, bu türlerin de önbellekte daha fazla yer kapladığını ve dolayısıyla bunları kullanmanın daha iyi performans sağlamayacağını unutmayın. Ayrıca, uygulamanın ilk etapta doğru seçimi yaptığına her zaman güvenilemez. Her zaman olduğu gibi, optimum sonuçlar için ölçüm gereklidir.


Android kullanıcıları için tablonun ekran görüntüsü:

Yukarıdaki tablonun ekran görüntüsü

(Android'in mono yazı tipinde kutu çizim karakterleri yoktur - ref )


Yorumlar uzun tartışmalar için değildir; bu sohbet sohbete taşındı .
Samuel Liew

"Tüm mimarilerde aynı değil" de doğrudur, ancak gösterilen verilerden hemen anlaşılır, bu yüzden açık olanı belirtmeyi gerekli görmüyorum. Yalnızca bir uygulamanın değerlerini gösterdim ve aslında diğerlerinin farklı seçenekleri olacak. Örneğin pencerelerde x86-64'ü kontrol edin. Burada gösterilene kıyasla farklı boyutlar bulacaksınız.
eerorika

@RobertSsupportsMonicaCellio Bence bu yorumlar cevap ile ilgilidir ve burada uygundur. İhtiyaç duyarlarsa bir moderatörün onları hareket ettirmesine izin verirdim.
eerorika

11

En azından güvenilir değiller.

Hızlı tipler normal tipler için typedefs'dir, ancak bunların nasıl tanımlanacağı uygulamaya bağlıdır. En azından istenen boyutta olmalılar, ancak daha büyük olabilirler.

Bazı mimarilerde bazı tamsayı türlerinin diğerlerinden daha iyi performans gösterdiği doğrudur. Örneğin, erken ARM uygulamalarında 32 bit sözcükler ve imzasız baytlar için bellek erişim talimatları vardı, ancak yarım sözcükler veya imzalı baytlar için talimatlar yoktu. Yarım sözcük ve imzalı bayt yönergeleri daha sonra eklenmiştir, ancak yedek kodlama alanına ayakkabı dolaştırılması gerektiğinden hala daha az esnek adresleme seçenekleri vardır. Ayrıca, ARM hakkındaki tüm gerçek veri işleme talimatları kelimeler üzerinde çalışır, bu nedenle bazı durumlarda doğru sonuçları vermek için hesaplamadan sonra daha küçük değerlerin maskelenmesi gerekebilir.

Bununla birlikte, daha küçük bir değer yüklemek / depolamak / işlemek için daha fazla talimat alsa bile, önbellek baskısının rekabet eden endişesi de vardır. Önbellek kaçırma sayısını azaltırsa daha küçük değer yine de daha iyi performans gösterebilir.

Birçok yaygın platformda tür tanımları düşünülmüş görünmemektedir. Özellikle, modern 64 bit platformlar 32 bit tamsayılar için iyi bir desteğe sahip olma eğilimindedir, ancak "hızlı" türler genellikle bu platformlarda gereksiz yere 64 bittir.

Ayrıca, C'deki türler platformun ABI'sinin bir parçası haline gelir. Bu nedenle, bir platform satıcısı aptal seçimler yaptığını fark etse bile, daha sonra bu aptal seçimleri değiştirmek zordur.

"Hızlı" türleri dikkate almayın. Tamsayı performansıyla ilgili endişeleriniz varsa, kodunuzu kullanılabilir tüm boyutlarla kıyaslayın.


7

Hızlı türler diğer tüm tamsayı türlerinden daha hızlı değildir - aslında bazı "normal" tamsayı türleriyle özdeştirler (sadece bu tür için bir takma addır) - hangi tür değeri tutmak için en hızlı olursa en azından bu kadar bit.

Her platforma hangi tamsayı türü için takma ad olduğu yalnızca platforma bağlıdır .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.