Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > 128-битные данные и арифметика


Автор: marcusmae 13.2.2008, 00:25
Всем привет,

Допустим, мне не хватает точности типа double, хочу использовать в два раза более длинное представление. Но поддержки компиляторами встроенного 128-битного вещественного (да и целого тоже) типа не наблюдаю, несмотря на то, что в C99 про него уже упоминается, да и компьютеры в промышленном производстве уже 4 года как с 64-битными регистрами (Которые, по-моему, реализуют поддержку операций с четверными словами на аппаратном уровне..?). 

Что же это такое? smile Никому не надо или какие-то у всех проблемы или я чего-то недоглядел? AFAIK, разброд полный :
  •  В M$ C/C++ есть целый выводок __m128i, __m128d и др., но применить их впрямую у меня не получилось
  •  Вместе с тем для M$ sizeof(double) = sizeof(long double) = 8, для других компиляторов sizeof(long double) случается равным 10 и 12. Но только не 16 smile А некоторые честно пишут, что not supported.
Короче, может кто-то применяет у себя 128-битные типы? Расскажите, пожалуйста, как.

Автор: bsa 13.2.2008, 01:03
marcusmae, вообще-то 64-х разряный процессор, это не значит, что он имеет 128-разрядные инструкции. Многое зависит от математического модуля (уже сопроцессором его называть язык не поворачивается). А еще больше - от компилятора.
А потом, неужели ты работаешь под 64-х разрядной ОС?
Код
#include <iostream>

int main()
{
        std::cout << "char:" << sizeof(char) << std::endl;
        std::cout << "short:" << sizeof(short) << std::endl;
        std::cout << "int:" << sizeof(int) << std::endl;
        std::cout << "long:" << sizeof(long) << std::endl;
        std::cout << "long long:" << sizeof(long long) << std::endl;
        std::cout << "float:" << sizeof(float) << std::endl;
        std::cout << "double:" << sizeof(double) << std::endl;
        std::cout << "long double:" << sizeof(long double) << std::endl;
        return 0;
}
Вывод:
Код
$ ./test 
char:1
short:2
int:4
long:8
long long:8
float:4
double:8
long double:16

gcc версия 4.1.2 (Gentoo 4.1.2)
Цитата(uname -a)

Linux bsa 2.6.23-gentoo-r6 #1 SMP PREEMPT Thu Jan 24 21:10:47 MSK 2008 x86_64 AMD Athlon™ 64 X2 Dual Core Processor 4600+ AuthenticAMD GNU/Linux


Автор: marcusmae 13.2.2008, 01:29
Цитата(bsa @  13.2.2008,  01:03 Найти цитируемый пост)
вообще-то 64-х разряный процессор, это не значит, что он имеет 128-разрядные инструкции


bsa, ну если процессор поддерживает SSE, то 128-битные инструкции у него есть smile Но это не суть важно,
Цитата(bsa @  13.2.2008,  01:03 Найти цитируемый пост)
А еще больше - от компилятора

вот именно. Дело, в первую очередь, в компиляторе, машинная поддержка - дело второе. Если инструкции не поддерживаются, то об этом можно выкинуть ошибку. Но я выразил удивление тому, что, на мой взгляд, качество компиляторов весьма заметно недотягивает до качества машин.

Цитата(bsa @  13.2.2008,  01:03 Найти цитируемый пост)
А потом, неужели ты работаешь под 64-х разрядной ОС?

Да.

Цитата

Microsoft Windows [Version 6.0.6000]
Copyright © 2006 Microsoft Corporation.  All rights reserved.

C:\Users\Mae Marcus>systeminfo

OS Name:                   MicrosoftR Windows VistaT Ultimate
OS Version:                6.0.6000 N/A Build 6000
OS Manufacturer:           Microsoft Corporation
OS Configuration:          Standalone Workstation
OS Build Type:             Multiprocessor Free
Registered Owner:          Mae Marcus
Registered Organization:
System Boot Time:          2/12/2008, 12:40:35 PM
System Type:               x64-based PC
Processor(s):              1 Processor(s) Installed.
                           [01]: EM64T Family 6 Model 15 Stepping 2 GenuineIntel
 ~1200 Mhz
BIOS Version:              American Megatrends Inc. 0706   , 5/2/2007
Total Physical Memory:     951 MB
Available Physical Memory: 95 MB
Page File: Max Size:       2,156 MB
Page File: Available:      595 MB
Page File: In Use:         1,561 MB


Тест :

Код

#include "stdafx.h"
#include <iostream>
#include <xmmintrin.h>
#include <emmintrin.h>

int _tmain(int argc, _TCHAR* argv[])
{
    std::cout << "char:" << sizeof(char) << std::endl;
    std::cout << "short:" << sizeof(short) << std::endl;
    std::cout << "int:" << sizeof(int) << std::endl;
    std::cout << "long:" << sizeof(long) << std::endl;
    std::cout << "long long:" << sizeof(long long) << std::endl;
    std::cout << "float:" << sizeof(float) << std::endl;
    std::cout << "double:" << sizeof(double) << std::endl;
    std::cout << "long double:" << sizeof(long double) << std::endl;

    std::cout << std::endl;
    std::cout << "__m128:" << sizeof(__m128) << std::endl;
    std::cout << "__m128i:" << sizeof(__m128i) << std::endl;
    std::cout << "__m128d:" << sizeof(__m128d) << std::endl;

    std::cin.get();
    return 0;
}


Код

char:1
short:2
int:4
long:4
long long:8
float:4
double:8
long double:8

__m128:16
__m128i:16
__m128d:16


Последние три типа являются структурами и предназначены, видимо, исключительно для внутреннего употребления. Так что вот, я не знаю, как 16 байт от него добиться...

Автор: Pulse69 13.2.2008, 07:27
Насколько я знаю, эти типы (__m128, __m128i, __m128d) применяются в наборе MS SIMD Intrinsics, т.е. инструкции процессора, позволяющие использовать Single Instruction Multiple Data модель.
Грубо говоря, в 128-битный тип __m128 запаковывают вектор из 2х 64-битных double чисел, потом два таких вектора можно, например, умножить одной инструкцией процессора (если он поддерживает SSE), и распаковать.
Т.е. попытка использовать типы SIMD intrinsics для повышения точности вычислений вряд ли даст желаемый эффект. 
Скорее, SIMD следует использовать для оптимизации работы с векторами и матрицами.

Автор: Lazin 13.2.2008, 10:33
есть еще аналогичный тип __m64 для работы с MMX, кстати у MS очень удобно работать с SIMD расширениями.
А использовать нужно __int64, __int128. 
Даже если процессор не позволяет работать с такими числами, все-равно возможна эмуляция. Можно-же использовать на 8-битном процессора не только байты))

Добавлено через 2 минуты и 10 секунд
Цитата(Pulse69 @  13.2.2008,  07:27 Найти цитируемый пост)
Насколько я знаю, эти типы (__m128, __m128i, __m128d) применяются в наборе MS SIMD Intrinsics

правильно знаешь)) 
могу добавить, что AFAIK они должны иметь определенное выравнивание, просто так их использовать нельзя

Автор: marcusmae 13.2.2008, 12:34
Цитата(Lazin @  13.2.2008,  10:33 Найти цитируемый пост)
Даже если процессор не позволяет работать с такими числами, все-равно возможна эмуляция.


Ну да, на то они называются intrinsics.

А вот как long double в gcc - полноценный тип?

Автор: bsa 14.2.2008, 00:03
marcusmae, а что ты понимаешь под словом "полноценный"? Это стандартный тип. Параметры которого не хуже, чем у double (так стандарт гласит?). судя по выводу моей проги, он отличается от double по размеру в 2 раза. Вот и все. Работать с ним никогда не приходилось.
Попутно нашел глюк у gcc:
sizeof(long long double) = 8;
long long double d = 123.455; //вызывает предупреждение о присвоении переменной типа long long int числа с плавающей точкой

Автор: marcusmae 14.2.2008, 00:19
bsa, спасибо!

Цитата(bsa @  14.2.2008,  00:03 Найти цитируемый пост)
Попутно нашел глюк у gcc:

неплохо smile

Цитата(bsa @  14.2.2008,  00:03 Найти цитируемый пост)
Работать с ним никогда не приходилось.

Ну, может, кто-то напишет, кому приходилось. А я тем временем выяснил, что long double поддерживается компиляторами gcc, IBM и, вроде бы, PGI.

Автор: Kappac 14.2.2008, 11:32
Такие ограничения скорей всего принадлежат операционке, потому как на разных системах один и тот же компилятор выдает разные результаты теста. В зависимости от потребностей можете попробовать использовать битовые последовательности. 

Автор: marcusmae 14.2.2008, 13:46
Kappac

Цитата(Kappac @  14.2.2008,  11:32 Найти цитируемый пост)
Такие ограничения скорей всего принадлежат операционке

думаю, не так однозначно, но отчасти да, возможно

Скажем, в Intel Fortran аналогом long double является тип real(16) - 16-байтовое вещественное. Просто поставил и поехал, а компилятор сам разберётся, как его проецировать на возможности ОС и оборудования. Аналогично, в .NET - тип decimal.

Цитата(Kappac @  14.2.2008,  11:32 Найти цитируемый пост)
 можете попробовать использовать битовые последовательности

Вы имете в виду специализированные пакеты типа арифметики больших чисел? = Вот я как раз расчитывал без них обойтись... Всё-таки long double - это не такая уж экзотика.

Автор: bsa 14.2.2008, 13:52
marcusmae, как видишь, гарантировать точность long double тебе никто не может.

Автор: marcusmae 14.2.2008, 14:04
Цитата(bsa @  14.2.2008,  13:52 Найти цитируемый пост)
как видишь, гарантировать точность long double тебе никто не может


Э... не вижу, где? Читаем help :

Цитата

REAL(16) Constants
A REAL(16) constant has more than four times the accuracy of a REAL(4) number, and a greater range.

A REAL(16) constant occupies 16 bytes of memory. The number of digits that precede the exponent is unlimited, but typically only the leftmost 33 digits are significant.

IEEE X_floating format is used.

Автор: bsa 14.2.2008, 15:10
marcusmae, а я разве что-то про real(16) говорил?

Автор: MAKCim 14.2.2008, 15:33
Цитата(bsa @  14.2.2008,  00:03 Найти цитируемый пост)
Попутно нашел глюк у gcc:
sizeof(long long double) = 8;

это точно компилируется?
разрядность процессора? разрядность ОС?
у меня С2D, 64-bit Linux, GCC 4.1.2
float = 4 (single precision)
double = 8 (double precision)
long double = 16 (double extended precision)

Автор: Kappac 14.2.2008, 20:50
Цитата(MAKCim @  14.2.2008,  15:33 Найти цитируемый пост)
long double = 16 (double extended precision) 

При всем моем глубоком уважении, Максим, это дейтсвительно так(long long double = 8). 



Цитата(marcusmae @  14.2.2008,  13:46 Найти цитируемый пост)
Вы имете в виду специализированные пакеты типа арифметики больших чисел? = Вот я как раз расчитывал без них обойтись... Всё-таки long double - это не такая уж экзотика.

Может стоит попробовать другой компилятор? Попробуйте, что на этот вопрос ответит gcc на вашей машине.

Автор: Alexeis 14.2.2008, 21:03
Цитата(MAKCim @  14.2.2008,  14:33 Найти цитируемый пост)
long double = 16 (double extended precision)

  В билдере это 10 байт, т.е. нативный тип для сопроцессора. Так что не какой гарантии.

Автор: MAKCim 14.2.2008, 21:59
Цитата(Kappac @  14.2.2008,  20:50 Найти цитируемый пост)
При всем моем глубоком уважении, Максим, это дейтсвительно так(long long double = 8). 

это не компилируется
по крайней мере на моей системе

Добавлено через 1 минуту и 18 секунд
Цитата(Alexeis @  14.2.2008,  21:03 Найти цитируемый пост)
В билдере это 10 байт, т.е. нативный тип для сопроцессора. Так что не какой гарантии. 

а я гарантий и не давал
просто задал вопрос bsa
он, скорее всего тоже на 64-х битной системе тестировал через GCC

Автор: Kappac 15.2.2008, 11:00
Цитата(MAKCim @  14.2.2008,  21:59 Найти цитируемый пост)
это не компилируется
по крайней мере на моей системе

Мои машины:
1. Turion MK36 x64, GCC - 4.1.2
2. Windows XP SP2 х86, GCC - 4.1.2
Компилируется и дает 8 байт. 

Автор: bsa 15.2.2008, 12:23
MAKCim
Цитата
Linux bsa 2.6.23-gentoo-r6 #1 SMP PREEMPT Thu Jan 24 21:10:47 MSK 2008 x86_64 AMD Athlon™ 64 X2 Dual Core Processor 4600+ AuthenticAMD GNU/Linux

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)