gpt4 book ai didi

cuda - 如何找到 CUDA 的 epsilon、min 和 max 常量?

转载 作者:行者123 更新时间:2023-12-03 20:39:39 25 4
gpt4 key购买 nike

我正在寻找 CUDA 设备的 epsilon(两个数字之间的最小步长)、min(最小幅度)和 max(最大幅度)的值。

I.E 相当于 <float.h> 中定义的 FLT_EPSILON (DBL_EPSILON)、FLT_MIN (DBL_MIN) 和 FLT_MAX (DBL_MAX)在 gcc 编译器中。

某些 CUDA 包含文件中是否有常量?
任何手册解释它们?有没有办法编写内核来计算它们?

提前致谢。

最佳答案

是的,如果您愿意,您当然可以自己计算这些。 couple examples关于如何计算机器 epsilon 在维基百科页面上以 C 语言给出;同样,您可以通过除以/乘以 2 直到下/溢出来找到最小值/最大值。 (然后您应该在最后一个有效值和下一个因子 2 之间搜索以找到“真实”的最小/最大值,但这为您提供了一个很好的起点)。

但是,如果您的设备的计算能力为 2.0 或更高,那么数学主要是 IEEE 754,有一些小偏差(例如,并非支持所有舍入模式),但这些偏差不足以影响像这样的基本数值常数;所以你会得到 5.96e-08 的单曲和 1.11e-16 的双曲的标准 emach; FLT_MIN/MAX 为 1.175494351e-38/3.402823466e+38,DBL_MIN/MAX 为 2.2250738585072014e-308/1.7976931348623158e+308。

在计算能力 1.3 的机器上,单精度不支持非规范化数字,因此您的 FLT_MIN 将明显大于 CPU。

在计算能力 2.0 机器上进行快速测试,对最小值/最大值进行快速而肮脏的计算:

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <cuda.h>
#include <sys/time.h>
#include <math.h>
#include <assert.h>
#include <float.h>

#define CHK_CUDA(e) {if (e != cudaSuccess) {fprintf(stderr,"Error: %s\n", cudaGetErrorString(e)); exit(-1);}}

/* from wikipedia page, for machine epsilon calculation */
/* assumes mantissa in final bits */
__device__ double machine_eps_dbl() {
typedef union {
long long i64;
double d64;
} dbl_64;

dbl_64 s;

s.d64 = 1.;
s.i64++;
return (s.d64 - 1.);
}

__device__ float machine_eps_flt() {
typedef union {
int i32;
float f32;
} flt_32;

flt_32 s;

s.f32 = 1.;
s.i32++;
return (s.f32 - 1.);
}

#define EPS 0
#define MIN 1
#define MAX 2

__global__ void calc_consts(float *fvals, double *dvals) {

int i = threadIdx.x + blockIdx.x*blockDim.x;
if (i==0) {
fvals[EPS] = machine_eps_flt();
dvals[EPS]= machine_eps_dbl();

float xf, oldxf;
double xd, oldxd;

xf = 2.; oldxf = 1.;
xd = 2.; oldxd = 1.;

/* double until overflow */
/* Note that real fmax is somewhere between xf and oldxf */
while (!isinf(xf)) {
oldxf *= 2.;
xf *= 2.;
}

while (!isinf(xd)) {
oldxd *= 2.;
xd *= 2.;
}

dvals[MAX] = oldxd;
fvals[MAX] = oldxf;

/* half until overflow */
/* Note that real fmin is somewhere between xf and oldxf */
xf = 1.; oldxf = 2.;
xd = 1.; oldxd = 2.;

while (xf != 0.) {
oldxf /= 2.;
xf /= 2.;
}

while (xd != 0.) {
oldxd /= 2.;
xd /= 2.;
}

dvals[MIN] = oldxd;
fvals[MIN] = oldxf;

}
return;
}

int main(int argc, char **argv) {
float fvals[3];
double dvals[3];
float *fvals_d;
double *dvals_d;

CHK_CUDA( cudaMalloc(&fvals_d, 3*sizeof(float)) );
CHK_CUDA( cudaMalloc(&dvals_d, 3*sizeof(double)) );

calc_consts<<<1,32>>>(fvals_d, dvals_d);

CHK_CUDA( cudaMemcpy(fvals, fvals_d, 3*sizeof(float), cudaMemcpyDeviceToHost) );
CHK_CUDA( cudaMemcpy(dvals, dvals_d, 3*sizeof(double), cudaMemcpyDeviceToHost) );

CHK_CUDA( cudaFree(fvals_d) );
CHK_CUDA( cudaFree(dvals_d) );

printf("Single machine epsilon:\n");
printf("CUDA = %g, CPU = %g\n", fvals[EPS], FLT_EPSILON);
printf("Single min value (CUDA - approx):\n");
printf("CUDA = %g, CPU = %g\n", fvals[MIN], FLT_MIN);
printf("Single max value (CUDA - approx):\n");
printf("CUDA = %g, CPU = %g\n", fvals[MAX], FLT_MAX);

printf("\nDouble machine epsilon:\n");
printf("CUDA = %lg, CPU = %lg\n", dvals[EPS], DBL_EPSILON);
printf("Double min value (CUDA - approx):\n");
printf("CUDA = %lg, CPU = %lg\n", dvals[MIN], DBL_MIN);
printf("Double max value (CUDA - approx):\n");
printf("CUDA = %lg, CPU = %lg\n", dvals[MAX], DBL_MAX);

return 0;
}

编译/运行表明答案与 CPU 版本一致(最小值除外;FLT_MIN 是否给出了最小值的正常值,而不是在 CPU 上取消规范?)
$ nvcc -o foo foo.cu -arch=sm_20
$ ./foo
Single machine epsilon:
CUDA = 1.19209e-07, CPU = 1.19209e-07
Single min value (CUDA - approx):
CUDA = 1.4013e-45, CPU = 1.17549e-38
Single max value (CUDA - approx):
CUDA = 1.70141e+38, CPU = 3.40282e+38

Double machine epsilon:
CUDA = 2.22045e-16, CPU = 2.22045e-16
Double min value (CUDA - approx):
CUDA = 4.94066e-324, CPU = 2.22507e-308
Double max value (CUDA - approx):
CUDA = 8.98847e+307, CPU = 1.79769e+308

关于cuda - 如何找到 CUDA 的 epsilon、min 和 max 常量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8812422/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com