X87 - 32 bit Derleme
X87 FPU yazısına göz atabilirsiniz.
fdiv
Sanırım bölme işlemi yapıyor.
fistp
float -> int çevrimi için kullanılır.
mov
Kullanım şekli şöyle.
Tüm modern işlemciler (Intel veya AMD) SSE2'yi desteklerler.Açıklaması şöyle.
Sanırım bölme işlemi yapıyor. gcc'de şöyle yaparız.
Elimizde bir dizi olsun.
Şöyle yaparız.
80 bitlik precision bazı C++ derleyicileri tarafından kullanılabiliyor. Açıklaması şöyle.
Aşağıdaki basit örnekte derleyicinin iki double sayısını çarparken fazla precision kullandığını görebiliriz.
32 ve 64'bitlik uygulamalar arasında da farklar olabilir.
C ile kullanılan long double 80 bitlik bu veri tipine denk gelebilir. Bu durumda iki farklı makine arasında aynı hesaplamayı yapsak bile farklı sonuçlar elde edilebilir. Derleyiciler strict mode çalışmaya zorlanarak farklı makineler arasında aynı sonucu elde etmek mümkün.
2. /fp:strict - MS derleyici için kullanılır
X87 FPU yazısına göz atabilirsiniz.
fdiv
Sanırım bölme işlemi yapıyor.
fistp
float -> int çevrimi için kullanılır.
mov
Kullanım şekli şöyle.
mov mem, reg
mov reg, mem
mov reg, reg
mov reg, imm
mov mem, imm
Açıklaması şöyleMost x86 instructions (other than some specialized instructions such as movsb) can only access one memory location. Therefore a move from memory to memory requires going through a register with two mov instructions.Elimizde şöyle bir kod olsun
x = y;
Assembly kodu şöyledirmovl -0x8(%rbp), %esi
movl %esi, -0xc(%rbp)
Streaming SIMD Extensions 2 - SSE2 - 64 bit DerlemeTüm modern işlemciler (Intel veya AMD) SSE2'yi desteklerler.Açıklaması şöyle.
SSE2 was introduced into Intel chips with the Pentium 4 in 2001 and AMD processors in 2003Visual Studio 2012'den itibaren 64 bit kodlar için SSE2 kodları üretiyor. SSE2 kodları XMM yazmaçlarını kullanır. Assembly kodu şöyledir
movsd QWORD PTR [rsp+8], xmm1
call cos
movsd xmm1, QWORD PTR [rsp+8]
movsd QWORD PTR [rsp], xmm0
movapd xmm0, xmm1
call cos
movsd xmm2, QWORD PTR [rsp]
ucomisd xmm2, xmm0
divssSanırım bölme işlemi yapıyor. gcc'de şöyle yaparız.
__m128 s1, s2;
s1 = _mm_set_ps(1.0, 1.0, 1.0, 1.0);
s2 = _mm_set_ps(0.0, 0.0, 0.0, 0.0);
s2 = _mm_div_ss(s1, s2);
_mm_loadu_si128 Elimizde bir dizi olsun.
short* tempBufferVert = new short[width * height];
Dizideki her elemanı 4 il bölmek için şöyle yaparız.#include <emmintrin.h> // SSE2
for (int i = 0; i < width * height; i += 8)
{
__m128i v = _mm_loadu_si128((__m128i *)&tempBufferVert[i]);
v = _mm_srai_epi16(v, 2); // v >>= 2
_mm_storeu_si128((__m128i *)&tempBufferVert[i], v);
}
setcsrŞöyle yaparız.
_mm_setcsr (0x00001D80);
Intel 80 bit floating point80 bitlik precision bazı C++ derleyicileri tarafından kullanılabiliyor. Açıklaması şöyle.
C# için de aynı kural geçerli.Açıklaması şöyle.The C++ standard allows implementations to evaluate floating-point expressions with more precision than the nominal type requires.
Bir başka açıklama şöyle.In particular, in some situations the JIT is permitted to use a more accurate intermediate representation - e.g. 80 bits when your original data is 64 bits - whereas in other situations it won't. That can result in seeing different results when any of the following is true:
ÖrnekThe IEEE 754 specifies that computations can be processed at a higher precision than what is stored in memory then rounded when written back to memory ..... In short, the standard does not promise that the same computation carried out on all hardware will return the same answer.
Aşağıdaki basit örnekte derleyicinin iki double sayısını çarparken fazla precision kullandığını görebiliriz.
#include <cstdint>
#include <cinttypes>
#include <cstdio>
using namespace std;
int main() {
double xd = 1.18;
int64_t xi = 1000000000;
int64_t res1 = (double)(xi * xd);
double d = xi * xd;
int64_t res2 = d;
printf("%" PRId64"\n", res1);
printf("%" PRId64"\n", res2);
}
Çıktı olarak şunu alırız.1179999999
1180000000
Örnek32 ve 64'bitlik uygulamalar arasında da farklar olabilir.
long double dvalue = 2.7182818284589998;
long double dexp = -0.21074699576017999;
long double result = std::powl( dvalue, dexp)
Sonuç olarak şunu alırız.64bit -> result = 0.80997896907296496 and 32bit -> result = 0.80997896907296507
FPU içindeki kayan nokta hesaplaması için kullanılan register'lar 80 bit olabiliyor.
C++
1. /fp:precise - MS derleyici için kullanılır
Varsayılan seçenek budur. Açıklaması şöyle
fp:precise weakens some of the rules, however it warranties that the precision of the calculations will not be lost.
Ara değerlerin (intermediate value) FPU registerlarında saklanmasına müsaade etmez. Hesaplamadan sonra ara değerler bellekteki alana geri yazılır. Açıklaması şöyle özellike x87 kodlarında bu açıklama önemli.
Bu seçenek Visual C++ 6.0 ile kullanılan /Op (Improve Float Consistency) seçeneğinin yerini almıştır. Eski seçenek için de benzer bir açıklama Açıklaması şöyleydiIf the value to be computed on is placed on a larger register then one computation is done and then the value is moved off of the register back to memory the result is truncated there. It could then be moved back on to the larger register for another computation.On the other hand if all the computations are done on the larger register before the value is moved back to memory you will get a different result.
By default, the compiler uses the coprocessor’s 80-bit registers to hold the intermediate results of floating-point calculations. This increases program speed and decreases program size. However, because the calculation involves floating-point data types that are represented in memory by less than 80 bits, carrying the extra bits of precision (80 bits minus the number of bits in a smaller floating-point type) through a lengthy calculation can produce inconsistent results.
Platformlar arasında uyumluluğu sağlamak için yukarıdaki gibi 80 bitlik floating point hesaplamalarını kullanılmaz. Açıklaması şöyle
Using fp:strict means that all the rules of IEEE 754 are respected. fp:strict is used to sustain bitwise compatibility between different compilers and platforms.
strictfp yazısına taşıdım
3. /fp:fast
Açıklaması şöyle
fp:fast allows compiler specific optimizations and transformations of expressions containing floating point calculation. It is the fastest methods but the results will differ between different compilers and platforms.
Hiç yorum yok:
Yorum Gönder