私が本当にメモリを求められており、より狭い範囲が必要であると仮定します(short
とint
に類似)。シェーダー言語はすでに、精度が半分の浮動小数点型のhalf
をサポートしています(値が-1から1になるように前後に変換するだけではなく、つまり、次のような浮動小数点数を返します:shortComingIn / maxRangeOfShort
)。 2バイトfloatの実装がすでに存在しますか?
また、2バイトの浮動小数点数がない理由(歴史的なもの)についても知りたいと思います。
Re:実装:誰かがC用にhalf
を書いたようです。これは(もちろん)C++で動作します: https://storage.googleapis.com/google-code-archive-downloads/v2 /code.google.com/cellperformance-snippets/half.c
Re:なぜfloat
が4バイトなのか:おそらくその下、 その精度は非常に制限されている が原因です。
メモリが少ない場合、フロートの概念を削除することを検討しましたか?浮動小数点数は、小数点がどこにあるかを保存するためだけに多くのビットを使用します。小数点を必要とする場所でknowを使用すると、これを回避できます。たとえば、ドル値を保存したい場合は、セントでそれを保存することができます:
uint16_t cash = 50000;
std::cout << "Cash: $" << (cash / 100) << "." << ((cash % 100) < 10 ? "0" : "") << (cash % 100) << std::endl;
もちろん、小数点の位置を事前に決定できる場合は、これが唯一のオプションです。ただし、可能であれば、常に優先してください。これにより、すべての計算が高速化されます。
rgds、Kira :-)
ありますisIEEE 754 standard for 16-bit floats 。
これは新しいフォーマットで、2002年にリリースされたGPUに基づいて2008年に標準化されました。
整数への切り替えでキラレインより少し先に進むには、範囲を定義し、shortの整数値が範囲全体で等しい除算を表すことを許可します。ゼロにまたがる場合は対称になります。
short mappedval = (short)(val/range);
これらの整数バージョンと半精度浮動小数点数の違い:
現在2つの一般的な標準16ビット浮動小数点形式があります:IEEE-754 binary16とGoogleのbfloat16。それらは標準化されているので、仕様を知っている人なら誰でも実装を作成できます。いくつかの例:
または、それらを使用したくない場合は、別の16ビット浮動小数点形式を設計して実装することもできます。
floatの精度でも通常の操作には十分ではないため、2バイトのfloatは通常使用されません。帯域幅やキャッシュサイズに制限されない限り、デフォルトでdouble
を常に使用する必要があります。 CおよびCのような言語で接尾辞なしで使用する場合、浮動小数点リテラルもdouble
です。見る
ただし、 32ビット未満の浮動小数点数は存在します 。それらは主にストレージの目的で使用されます。たとえば、グラフィックスの場合、ピクセルあたり96ビット(チャネルあたり32ビット* 3チャネル)が無駄になりすぎ、通常に変換されます。計算用の32ビット浮動小数点(一部の特別なハードウェアを除く)。 OpenGLには、さまざまな 10、11、14ビットの浮動小数点型 が存在します。多くのHDR形式は各チャネルに16ビットの浮動小数点を使用し、Direct3D 9.0とRadeon R300やR420などの一部のGPUは24ビットの浮動小数点形式を持っています。 24ビット浮動小数点は、一部の8ビットマイクロコントローラーの コンパイラでもサポートされています[〜#〜] pic [〜#〜] 32ビットfloatのサポートにはコストがかかりすぎます。 8ビット以下の浮動小数点型はあまり有用ではありませんが、その単純さのため、コンピュータサイエンスのカリキュラムでよく教えられています。さらに、 ARMの命令エンコーディング で小さな浮動小数点が使用され、小さな浮動小数点の即値も使用されます。
IEEE 754-2008リビジョン は、16ビットの浮動小数点形式、AKAbinary16または 半精度 、5ビットの指数と11ビットの仮数
一部のコンパイラはIEEE-754バイナリ16をサポートしていましたが、主に変換またはベクトル化された演算をサポートし、計算はサポートしていませんでした(十分に正確ではないため)。たとえば、ARMのツールチェーンには __fp16
があり、より多くの範囲またはNaN/inf表現が必要かどうかに応じて、IEEEと代替の2つのバリアントから選択できます。 [〜#〜] gcc [〜#〜] および Clang は、標準化された名前__fp16
とともに_Float16
もサポートします。 x86_64 のgccで__fp16タイプを有効にする方法を参照してください
最近AIの台頭により、 bfloat16 ( brain floating)と呼ばれる別の形式-point format )は、IEEE-754 binary32の上位16ビットの単純な切り捨てであり、一般的になりました
仮数の削減の背後にある動機は、トレーニング中に小さな差の合計の一部としてゼロに近い小さな値を表すことが可能である限り、仮数を削減しても問題ないことを示したGoogleの実験に由来します。仮数を小さくすると、乗算器の消費電力やシリコンの物理的な面積が小さくなるなど、他にも多くの利点があります。
- float32:242 = 576(100%)
- float16:112 = 121(21%)
- bfloat16:82 = 64(11%)
[〜#〜] gcc [〜#〜] や [〜#〜] icc [〜#〜] などの多くのコンパイラもbfloat16をサポートする能力を獲得しました
Bfloat16の詳細:
異なる実装には、おそらくさまざまなタイプがあります。 stdint.hに相当するfloatは良い考えのようです。サイズでタイプを(別名?)呼び出します。 (float16_t?)floatが4バイトであるのは今のところですが、おそらく小さくなりません。 halfやlongなどの用語は、時間の経過とともにほとんど意味がなくなります。 128ビットまたは256ビットのコンピューターでは、何を意味するようになる可能性があります。
画像(1 + 1 + 1バイト/ピクセル)で作業していて、平均に対する各ピクセルの値を表現したいと思います。したがって、浮動小数点または慎重に固定された点ですが、生データの4倍ではありません。 16ビットのフロートはほぼ正しい音です。
このGCC 7.3は「半分」を知らない、おそらくC++のコンテキストで。
CPUがF16Cをサポートしている場合は、次のようなものを使用して、かなり迅速に何かを起動して実行できます。
// needs to be compiled with -mf16c enabled
#include <immintrin.h>
#include <cstdint>
struct float16
{
private:
uint16_t _value;
public:
inline float16() : _value(0) {}
inline float16(const float16&) = default;
inline float16(float16&&) = default;
inline float16(const float f) : _value(_cvtss_sh(f, _MM_FROUND_CUR_DIRECTION)) {}
inline float16& operator = (const float16&) = default;
inline float16& operator = (float16&&) = default;
inline float16& operator = (const float f) { _value = _cvtss_sh(f, _MM_FROUND_CUR_DIRECTION); return *this; }
inline operator float () const
{ return _cvtsh_ss(_value); }
inline friend std::istream& operator >> (std::istream& input, float16& h)
{
float f = 0;
input >> f;
h._value = _cvtss_sh(f, _MM_FROUND_CUR_DIRECTION);
return input;
}
};
計算は引き続き32ビットフロートを使用して実行されます(F16C拡張は16/32ビットフロート間の変換のみを提供します。16ビットフロートでの計算を計算するための命令はありません)。