대신 doubles가 주로 권장되는 경우 float가 여전히 Java 언어의 일부입니까?


84

내가 본 모든 곳에서, 그것은 거의 모든면에서 double우월하다고 말합니다 float. Java에서 float더 이상 사용되지 double않으므로 왜 여전히 사용됩니까?

나는 Libgdx로 많은 프로그램을 만들고, 그것들을 사용하도록 강요 float하지만 (deltaTime 등) double저장 및 메모리 측면에서 작업하기가 더 쉬운 것 같습니다 .

나는 언제 float을 사용하고 double을 사용합니까 ?를 읽습니다 . 그러나 float소수점 뒤에 많은 숫자가있는 숫자에만 실제로 좋은 경우 왜 우리는 왜 많은 변형 중 하나를 사용할 수 double없습니까?

더 이상 이점이 없지만 플로트 사용을 주장하는 이유가 있습니까? 모든 것을 바꾸는 것이 너무 많은 일입니까?



58
이 질문에 대한 대답에서 "부동 소수점은 소수점 이하 자릿수가 많은 숫자에만 실제로 유효합니다"라고 어떻게 추론 했습니까? 그들은 직접 반대 라고 말합니다 !
Ordous

20
@Eames "숫자"가 아니라 "숫자"라고 말하는 방법에 주목하십시오. 수레는 는 정밀도 또는 범위를 필요로 할 때, 그들이 더 나은 당신이 많고 그다지 정확하지 많은 데이터를 필요로 할 때. 이것이 바로 그 대답입니다.
Ordous

29
우리는 왜해야합니까 byteshortint때 거기에 long?
immibis

15
더 적합한 질문은 "왜 아무 이유없이 깨질 수십 년의 코드를 가진 언어에서 키워드와 기본 데이터 유형을 제거하겠습니까?"입니다.
sara

답변:


169

LibGDX는 주로 게임 개발에 사용되는 프레임 워크입니다.

게임 개발에서는 일반적으로 실시간으로 많은 수의 크 런칭을 수행하고 문제를 해결할 수있는 성능을 수행해야합니다. 그렇기 때문에 게임 개발자는 float 정밀도가 충분할 때마다 float를 사용합니다.

이 경우 CPU에서 FPU 레지스터의 크기 만 고려할 필요는 없습니다. 실제로 게임 개발에서 많은 수의 크 런칭은 GPU에 의해 수행되며 GPU는 일반적으로 double이 아닌 float에 최적화됩니다 .

그리고 다음도 있습니다.

  • 메모리 버스 대역폭 (RAM, CPU 및 GPU간에 데이터를 얼마나 빨리 삽질 할 수 있는지)
  • CPU 캐시 (이전이 덜 필요함)
  • VRAM

64bit double 대신 32bit float를 사용할 때 두 배나 많은 귀중한 자원입니다.


2
감사합니다! 메모리 사용량의 변화와 그 이유에 대해 깊이 이해했기 때문에 실제로 도움이되었습니다.
Eames

7
또한 SIMD 작업의 경우 32 비트 값의 처리량이 두 배가 될 수 있습니다. 8 비트 트리의 답변에서 알 수 있듯이 GPU는 배정 밀도로 성능이 크게 저하됩니다.
Paul A. Clayton

5
많은 그래픽 파이프 라인은 16 비트 반 부동을 지원하여 정밀도가 충분한 경우 성능을 향상시킵니다.
Adi Shavit

22
@phresnel 모두 있습니다. 위치를 이동하고 데이터를 업데이트해야합니다. 그리고 이것은 간단한 부분입니다. 그런 다음 텍스처, 거리를 렌더링 (= 읽기, 회전, 크기 조정 및 변환)하고 화면 형식으로 가져와야합니다 ...해야 할 일이 많이 있습니다.
Sebb

8
@phresnel은 게임 개발 기업의 전 부사장으로서 거의 모든 게임에 엄청난 수의 크 런칭이 있음을 확신합니다. 일반적으로 라이브러리에 포함되어 있으며 엔지니어로부터 100 % 추상화되어 있기 때문에 모든 크 런칭이 진행되고 있음을 이해하고 존중하기를 바랍니다. 마법의 역 제곱근, 누구?
corsiKa

57

플로트는 두 배의 절반만큼 메모리를 사용합니다.

그것들은 배가보다 정밀도가 떨어질 수 있지만, 많은 어플리케이션들은 정밀도를 요구하지 않습니다. 그것들은 비슷한 크기의 고정 소수점 형식보다 넓은 범위를 가지고 있습니다. 따라서 광범위한 숫자가 필요하지만 높은 정밀도가 필요하지 않고 메모리 사용이 중요한 틈새 시장을 채 웁니다. 예를 들어 과거에 대형 신경망 시스템에 사용했습니다.

Java 외부로 이동하면 많은 GPU가 GPU를 기본 형식으로 사용하기 때문에 3D 그래픽에서도 널리 사용됩니다. 고가의 NVIDIA Tesla / AMD FirePro 장치 외부에서는 배정 밀도 부동 소수점이 GPU에서 매우 느립니다.


8
신경망과 관련하여 CUDA는 현재 기계 학습 작업을위한 가속기의 사용이 증가함에 따라 반 정밀도 (16 비트) 부동 소수점 변수를 지원하지만 정확도는 떨어지지 만 메모리 풋 프린트는 훨씬 적습니다.
JAB

그리고 FPGA를 프로그래밍 할 때마다 매번 가수와 지수 모두에 대한 비트의 양을 선택하는 경향이 있습니다 : v
Sebi

48

이전 버전과의 호환성

이것이 이미 존재하는 언어 / 라이브러리 / ISA / etc 에서 동작을 유지하는 가장 큰 이유입니다 .

Java에서 수레를 가져간 경우 어떻게 될지 고려하십시오. Libgdx (및 수천 개의 다른 라이브러리 및 프로그램)가 작동하지 않습니다. 많은 프로젝트에서 아마도 몇 년 동안 모든 것을 업데이트하기 위해 많은 노력을 기울일 것입니다 (역 호환성을 깨는 Python 2에서 Python 3 로의 전환을 살펴보십시오). 그리고 모든 것이 업데이트되지는 않을 것입니다. 유지 보수 담당자가 포기했기 때문에 어떤 것이 영원히 깨질 것입니다. 아마도 업데이트보다 더 많은 노력이 필요하거나 소프트웨어가 생각한 것을 성취 할 수 없기 때문에 이전보다 더 빨리 할 것.

공연

64 비트 더블은 메모리를 두 배로 차지하고 32 비트 플로트보다 처리 속도가 거의 느립니다 (32 비트 플로트 기능을 거의 사용하지 않거나 전혀 사용하지 않는 경우는 예외). 특수 하드웨어 용으로 개발하지 않는 한 가까운 시일 내에이를 경험하지 못할 것입니다.)

특히 Libgdx는 게임 라이브러리입니다. 게임은 대부분의 소프트웨어보다 성능에 더 민감한 경향이 있습니다. 게임 그래픽 카드 (예 : FirePro 또는 Quadro가 아닌 AMD Radeon 및 NVIDIA Geforce)는 64 비트 부동 소수점 성능이 매우 약한 경향이 있습니다. Anandtech의 의례, 다음은 AMDNVIDIA 최고의 게임 카드 중 일부에서 배정 밀도 성능을 단 정밀도 성능과 비교하는 방법입니다 (2016 년 초 기준).

AMD
Card    R9 Fury X      R9 Fury       R9 290X    R9 290
FP64    1/16           1/16          1/8        1/8

NVIDIA
Card    GTX Titan X    GTX 980 Ti    GTX 980    GTX 780 Ti
FP64    1/32           1/32          1/32       1/24

R9 Fury 및 GTX 900 시리즈는 R9 200 및 GTX 700 시리즈보다 최신이므로 64 비트 부동 소수점에 대한 상대적인 성능이 감소합니다. 충분히 되돌아 가면 R9 200 시리즈와 같은 1/8 비율의 GTX 580을 찾을 수 있습니다.

시간 제한이 빡빡하고 더 큰 더블을 사용하여 많은 것을 얻지 못하면 성능의 1/32가 지불하는 것이 큰 페널티입니다.


1
실제로 64 비트 부동 소수점의 성능은 실제 64 비트 성능이 감소하기 때문이 아니라 점점 더 최적화 된 32 비트 명령어로 인해 32 비트 성능에 비해 감소합니다. 또한 사용 된 실제 벤치 마크에 따라 다릅니다. 32 비트 성능 적자가 이러한 벤치 마크에서 강조 있을지 계산 속도의 메모리 대역폭 문제로 인해뿐만 아니라 실제 궁금해
sig_seg_v가

그래픽 카드의 DP 성능에 대해 이야기하려면 Titan / Titan Black을 언급해야합니다. 두 가지 기능 모두 단 정밀도 성능으로 카드가 1/3 성능에 도달 할 수 있도록합니다.
SGR

@sig_seg_v 64 비트 성능이 상대적으로가 아니라 절대적으로 감소하는 경우가 있습니다. GTX 780 Ti가 GTX 1080 (다른 1/32 비율 카드)과 980Ti를 모두 능가하는 AMD 및 7970 (1/4 비율 카드)을 능가하는 배정 밀도 folding @ Home 벤치 마크에 대해서는 이 결과 를 참조하십시오. R9 290 및 R9 290X는 물론 R9 Fury 시리즈를 능가했습니다. 새로운 카드가 모두 이전 모델보다 성능이 우수한 벤치 마크단 정밀도 버전과 비교해보십시오 .
비트 트리

36

원자력 운영

다른 사람들이 이미 말한 것 외에도 Java의 단점은 double(및 long) 64 비트 기본 유형에 대한 할당이 원 자성으로 보장되지 않는다는 것 입니다. 660 페이지 의 Java 언어 사양, Java SE 8 Edition (강조 추가)에서 :

17.7 비 처리 원자 doublelong

Java 프로그래밍 언어 메모리 모델의 목적을 위해 비 휘발성 long또는 double값에 대한 단일 쓰기 는 두 개의 개별 쓰기 (각각 32 비트 반에 하나씩)로 처리됩니다. 스레드가 한 쓰기에서 64 비트 값의 첫 32 비트를보고 다른 쓰기에서 두 번째 32 비트를 보는 상황이 발생할 수 있습니다 .

왝.

이를 피하려면 키워드를 사용 하여 64 비트 변수volatile선언 하거나 할당에 대해 다른 형식의 동기화를 사용해야 합니다.


2
업데이트 손실을 방지하고 과도한 캐싱을 방지하기 위해 업데이트를 휘발성으로 만들기 위해 int 및 float에 대한 동시 액세스를 동기화 할 필요가 없습니까? int / float 원자가 막을 수있는 유일한 것은 그들이 보유하지 말아야 할 "혼합 된"값을 절대 포함 할 수 없다는 것입니다.
Traubenfuchs

3
@Traubenfuchs 즉, 실제로 보장되는 것입니다. 내가 들었던 용어는 "찢어짐"이며 효과를 아주 잘 포착한다고 생각합니다. Java 프로그래밍 언어 모델은 읽을 때 32 비트 값이 어느 시점에서 작성된 값을 갖도록합니다. 그것은 놀랍게도 귀중한 보증입니다.
Cort Ammon

원자성에 대한이 점은 매우 중요합니다. 와우, 나는이 중요한 사실을 잊었다. 우리가 기본 요소를 본질적으로 원자 적이라고 생각하는 경향이있는 반 직관적. 그러나이 경우 원자가 아닙니다.
Basil Bourque

3

다른 답변은 한 가지 중요한 점을 놓친 것 같다 다음 SIMD의 가에 운영하는 경우 구조가 따라 이하 / 더 많은 데이터를 처리 할 수 double또는 float구조체 (예를 들어, 한 번에 여덟 개 부동 소수점 값, 또는 한 번에 네 번 값).

성능 고려 사항 요약

  • float 특정 CPU (예 : 특정 모바일 장치)에서 더 빠를 수 있습니다.
  • float 적은 메모리를 사용하므로 대량의 데이터 세트에서 필요한 총 메모리 (하드 디스크 / RAM) 및 소비되는 대역폭을 크게 줄일 수 있습니다.
  • float 배정 밀도 계산에 비해 단 정밀도 계산에 대해 CPU가 더 적은 전력을 소비하게 할 수 있습니다 (참조를 찾을 수는 없지만 적어도 가능하지 않은 경우).
  • float 더 적은 대역폭과 일부 응용 프로그램에서 소비합니다.
  • SIMD 아키텍처는 일반적으로 동일한 양의 데이터를 두 배나 많이 처리 할 수 ​​있습니다.
  • float 두 배에 비해 캐시 메모리의 절반을 사용합니다.

정확도 고려 사항 요약

  • 많은 응용 프로그램 float에서 충분
  • double 어쨌든 훨씬 더 정밀한

호환성 고려 사항

  • 데이터를 GPU에 제출해야하는 경우 (예 : OpenGL을 사용하는 비디오 게임 또는 기타 렌더링 API) 부동 소수점 형식이 doubleGPU 보다 훨씬 빠릅니다 (GPU 제조업체가 그래픽 코어 수를 늘리려 고하기 때문입니다. 따라서 그들은 각 코어에서 가능한 많은 회로를 절약하려고 노력하므로 최적화 float하면 더 많은 코어가있는 GPU를 만들 수 있습니다)
  • 구형 GPU 및 일부 모바일 장치 double는 내부 형식으로 만 사용할 수 없습니다 (3D 렌더링 작업의 경우)

일반적인 팁

  • 최신 데스크탑 프로세서 (및 아마도 많은 양의 모바일 프로세서)에서는 기본적으로 double스택에서 임시 변수를 사용 하면 추가 정밀도를 무료로 제공 한다고 가정 할 수 있습니다 (성능 저하없이 추가 정밀도).
  • 필요한 것보다 더 높은 정밀도를 사용하지 마십시오 (실제로 필요한 정밀도를 모를 수 있습니다).
  • 때때로 당신은 단지 값의 범위에 의해 강제됩니다 (일부 값은을 사용하는 경우 무한 float하지만을 사용하는 경우 제한된 값 일 수 있습니다 double)
  • 단지 사용 float또는 만 double크게하는 지침을 SIMD가-쓸어하도록 컴파일러에 도움이됩니다.

자세한 내용은 PeterCordes의 아래 의견을 참조하십시오.


1
double임시는 SSE2가 아니라 x87 FPU가있는 x86에서만 무료입니다. double임시 로 루프를 자동 벡터화하는 것은의 압축 float을 풀다는 것을 의미 double하며 추가 명령이 필요하며 벡터 당 절반의 요소를 처리합니다. 자동 벡터화를 사용하지 않으면 일반적으로로드 또는 저장 중에 변환이 즉시 발생할 수 있지만 표현식에서 float와 double을 혼합 할 때는 추가 지침이 필요합니다.
Peter Cordes

1
최신 x86 CPU에서는 div 및 sqrt가 double보다 float보다 빠르지 만 다른 속도는 동일합니다 (SIMD 벡터 너비 문제 나 메모리 대역폭 / 캐시 풋 프린트는 포함하지 않음).
Peter Cordes

@PeterCordes는 포인트를 늘려 주셔서 감사합니다. 나는 div와 sqrt의 차이를
알지 못했습니다

0

언급 된 다른 이유들과 별도로 :

압력, 유량, 전류, 전압 등 무엇이든 측정 데이터가있는 경우, 이는 종종 ADC가있는 하드웨어에서 수행됩니다.

ADC는 일반적으로 10 비트 또는 12 비트, 14 비트 또는 16 비트는 드물다. 그러나 16 비트 1을 고수합시다. 실제로 측정하면 1/65535의 정확도를 갖습니다. 즉 65534/65535에서 65535/65535 로의 변경은이 단계 인 1/65535에 불과합니다. 대략 1.5E-05입니다. 플로트의 정확도는 1E-07 정도이므로 훨씬 좋습니다. 즉, float이러한 데이터를 저장하는 데 사용 하면 아무것도 손실되지 않습니다 .

당신이 할 경우 과도한 수레로 계산을하면보다 살짝 더 수행 doubles정확도 측면에서, 그러나 수시로 방금 마찬가지로 2 V 또는 2.00002 V.의 전압을 측정하는 경우가 종종 상관하지 않는 한, 그 정확성을 필요로하지 않습니다 ,이 전압을 압력으로 변환하면 3 bar 또는 3.00003 bar가 있는지 상관하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.