我想知道为什么对Float64
值进行操作比对 进行操作更快Float16
:
julia> rnd64 = rand(Float64, 1000);\n\njulia> rnd16 = rand(Float16, 1000);\n\njulia> @benchmark rnd64.^2\nBenchmarkTools.Trial: 10000 samples with 10 evaluations.\n Range (min \xe2\x80\xa6 max): 1.800 \xce\xbcs \xe2\x80\xa6 662.140 \xce\xbcs \xe2\x94\x8a GC (min \xe2\x80\xa6 max): 0.00% \xe2\x80\xa6 99.37%\n Time (median): 2.180 \xce\xbcs \xe2\x94\x8a GC (median): 0.00%\n Time (mean \xc2\xb1 \xcf\x83): 3.457 \xce\xbcs \xc2\xb1 13.176 \xce\xbcs \xe2\x94\x8a GC (mean \xc2\xb1 \xcf\x83): 12.34% \xc2\xb1 3.89%\n\n \xe2\x96\x81\xe2\x96\x88\xe2\x96\x88\xe2\x96\x84\xe2\x96\x82\xe2\x96\x82\xe2\x96\x86\xe2\x96\x86\xe2\x96\x84\xe2\x96\x82\xe2\x96\x81 \xe2\x96\x82\xe2\x96\x86\xe2\x96\x84\xe2\x96\x81 \xe2\x96\x82\xe2\x96\x82\xe2\x96\x82\xe2\x96\x81 \xe2\x96\x82\n \xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x87\xe2\x96\x87\xe2\x96\x86\xe2\x96\x86\xe2\x96\x87\xe2\x96\x86\xe2\x96\x85\xe2\x96\x87\xe2\x96\x88\xe2\x96\x88\xe2\x96\x86\xe2\x96\x86\xe2\x96\x85\xe2\x96\x85\xe2\x96\x86\xe2\x96\x84\xe2\x96\x84\xe2\x96\x81\xe2\x96\x81\xe2\x96\x83\xe2\x96\x83\xe2\x96\x81\xe2\x96\x81\xe2\x96\x84\xe2\x96\x81\xe2\x96\x83\xe2\x96\x84\xe2\x96\x81\xe2\x96\x83\xe2\x96\x81\xe2\x96\x84\xe2\x96\x83\xe2\x96\x81\xe2\x96\x81\xe2\x96\x86\xe2\x96\x87\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x87 \xe2\x96\x88\n 1.8 \xce\xbcs Histogram: log(frequency) by time 10.6 \xce\xbcs <\n\n …
Run Code Online (Sandbox Code Playgroud) 假设我真的被迫记忆并想要一个更小的范围(类似于短与int).着色器语言已经支持short
具有精度一半的浮点(不只是来回转换为-1到1之间的值,也就是说,像这样返回一个浮点数:) int
.是否存在2字节浮点数已经存在的实现?
我也有兴趣知道为什么没有2字节浮点数的任何(历史?)原因.
的__fp16
浮点数据类型是一个众所周知的扩展上的ARM处理器特别是所使用的C标准.我想在我的x86_64处理器上运行它们的IEEE版本.虽然我知道他们通常没有这个,但我可以用"无符号短"存储(它们具有相同的对齐要求和存储空间)和(硬件)浮点算法来模拟它们.
有没有办法在gcc中请求?
我认为舍入可能稍微"不正确",但这对我来说没问题.
如果这也适用于C++,那将是理想的.
您将如何确定最适合您的推理模型的精度?BF16 和 F16 都占用两个字节,但它们对分数和指数使用不同的位数。
\n范围会有所不同,但我试图理解为什么人们选择其中之一而不是其他。
\n谢谢
\n |--------+------+----------+----------|\n | Format | Bits | Exponent | Fraction |\n |--------+------+----------+----------|\n | FP32 | 32 | 8 | 23 |\n | FP16 | 16 | 5 | 10 |\n | BF16 | 16 | 8 | 7 |\n |--------+------+----------+----------|\n\nRange\nbfloat16: ~1.18e-38 \xe2\x80\xa6 ~3.40e38 with 3 significant decimal digits.\nfloat16: ~5.96e\xe2\x88\x928 (6.10e\xe2\x88\x925) \xe2\x80\xa6 65504 with 4 significant decimal digits precision.\n\n
Run Code Online (Sandbox Code Playgroud)\n machine-learning deep-learning tensorflow pytorch half-precision-float
是否可以在英特尔芯片上执行半精度浮点运算?
我知道如何加载/存储/转换半精度浮点数[1],但我不知道如何在不转换为单精度浮点数的情况下添加/相乘它们.
[1] https://software.intel.com/en-us/articles/performance-benefits-of-half-precision-floats
x86 intel avx floating-point-conversion half-precision-float
我正在用 float2 向量填充 MTLBuffer。缓冲区正在被创建和填充,如下所示:
struct Particle {
var position: float2
...
}
let particleCount = 100000
let bufferSize = MemoryLayout<Particle>.stride * particleCount
particleBuffer = device.makeBuffer(length: bufferSize)!
var pointer = particleBuffer.contents().bindMemory(to: Particle.self, capacity: particleCount)
pointer = pointer.advanced(by: currentParticles)
pointer.pointee.position = [x, y]
Run Code Online (Sandbox Code Playgroud)
在我的 Metal 文件中,缓冲区的访问方式如下:
struct Particle {
float2 position;
...
};
kernel void compute(device Particle *particles [[buffer(0)]], … )
Run Code Online (Sandbox Code Playgroud)
我需要在我的 Metal 计算内核中使用半精度浮点数。在 Metal 方面,就像为数据类型指定 half2 一样简单。
在 CPU 方面,用半精度浮点数填充缓冲区的最佳方法是什么?
我试图在编译时确定_Float16
受支持的:
#define __STDC_WANT_IEC_60559_TYPES_EXT__
#include <float.h>
#ifdef FLT16_MAX
_Float16 f16;
#endif
Run Code Online (Sandbox Code Playgroud)
调用:
# gcc trunk on linux on x86_64
$ gcc -std=c11 -pedantic -Wall -Wextra
t0.c:4:1: warning: ISO C does not support the '_Float16' type [-Wpedantic]
# clang trunk on linux on x86_64
$ clang -std=c11 -pedantic -Wall -Wextra
t0.c:4:1: error: _Float16 is not supported on this target
Run Code Online (Sandbox Code Playgroud)
在这里我们看到 gcc 和 clang:
FLT16_MAX
_Float16
主要问题:如何在编译时正确判断_Float16
是支持的?
额外的问题:如果不支持相应的浮点类型,C11(或更新的)标准是否要求不定义 _MIN
/宏?_MAX
例如,对于整数类型 ( <stdint.h>
),它是正确的:“也不应定义关联的宏”(C11,7.20 整数类型 <stdint.h>,4)。浮动类型也一样吗? …
很明显为什么 16 位浮点格式开始用于机器学习;它降低了存储和计算的成本,而且神经网络对数字精度出人意料地不敏感。
\n我发现特别令人惊讶的是,从业者放弃了已经定义的半精度格式,转而只为有效数分配 7 位,但为指数 \xe2\x80\x93 分配 8 位,完全与 32 位 FP 一样多。(维基百科将 Brain-floatbfloat16
布局与 IEEE binary16 和某些 24 位格式进行了比较。)
为什么有这么多指数位?到目前为止,我只找到了https://cloud.google.com/blog/products/ai-machine-learning/bfloat16-the-secret-to-high-performance-on-cloud-tpus
\n\n\n根据我们多年来在 Google\xe2\x80\x99s 产品和服务中训练和部署各种神经网络的经验,我们在设计 Cloud TPU 时就知道,神经网络对指数大小的敏感度远远高于对指数大小的敏感度。尾数。为了确保下溢、溢出和 NaN 具有相同的行为,bfloat16 具有与 FP32 相同的指数大小。然而,bfloat16 处理非正规数的方式与 FP32 不同:它将它们刷新为零。与 FP16 不同,FP16 通常需要通过损失缩放 [Mic 17] 等技术进行特殊处理,在训练和运行深度神经网络时,BF16 几乎可以替代 FP32。
\n
我还没有在像谷歌这样的规模上运行过神经网络实验,但是在我运行过的实验中,绝对值远大于 1.0 的权重或激活意味着它已经陷入困境,将会螺旋式上升无穷大,如果计算机立即崩溃并显示错误消息,那对您来说是有好处的。我从未见过或听说过任何需要像单精度浮点 1e38 这样的动态范围的情况。
\n那么我错过了什么?
\n在某些情况下,神经网络确实需要巨大的动态范围吗?如果是这样,如何,为什么?
\n是否有某种原因认为 bfloat16 使用相同的指数作为单精度非常有益,即使有效数要小得多?
\n还是真正的目标是将有效数缩小到可以完成工作的绝对最小值,以最大限度地减少乘法器的芯片面积和能源成本(FPU 中最昂贵的部分)?碰巧这大约是 7 位;出于对齐原因,总大小应为 2 的幂;它不太适合 8 位;增加到 16,留下的多余位也可以用于某些用途,而最优雅的解决方案是保留 8 位指数?
\nfloating-point machine-learning cpu-architecture neural-network half-precision-float
示例代码:
#include <stdio.h>
#define __STDC_WANT_IEC_60559_TYPES_EXT__
#include <float.h>
#ifdef FLT16_MAX
_Float16 f16;
int main(void)
{
printf("%f\n", f16);
return 0;
}
#endif
Run Code Online (Sandbox Code Playgroud)
调用:
# gcc trunk on linux on x86_64
$ gcc t0.c -std=c11 -Wall
Run Code Online (Sandbox Code Playgroud)
预期诊断:
<nothing>
Run Code Online (Sandbox Code Playgroud)
实际诊断:
t0.c:9:14: warning: format '%f' expects argument of type 'double', but argument 2 has type '_Float16' [-Wformat=]
9 | printf("%f\n", f16);
| ~^ ~~~
| | |
| | _Float16
| double
Run Code Online (Sandbox Code Playgroud)
这是否意味着在__STDC_WANT_IEC_60559_TYPES_EXT__
AND 下如果FLT16_MAX
定义了 gcc 不知道printf
可以与 一起使用_Float16
?是否应该有所了解? …
_mm256_mul_ps
是“乘法打包单精度(32 位)浮点元素”的 Intel 内在函数。_mm256_mul_ph
是“乘法打包半精度(16 位)浮点元素”的内在函数。
我可以_mm256_mul_ps
使用 using 来调用use std::arch::x86_64::*;
,例如
#[inline]
fn mul(v: __m256, w: __m256) -> __m256 {
unsafe { _mm256_mul_ps(v, w) }
}
Run Code Online (Sandbox Code Playgroud)
不过,似乎很难调用_mm256_mul_ph
。可以调用_mm256_mul_ph
Rust 吗?