I have a large Fortran/C++ project that assembles hundreds of Fortran intermediate files into a single executive. When I monitor some of the global single precision floating point variables, I get different results when I run the executive on a Windows 7 x64 machine vs a Windows XP SP2 x86 machine. The differences are as much as 1-2%.
The project was built on the x86 machine and not rebuilt before testing on the x64 machine, although I am using the exact same compiler (compaq visual fortran 6.6), and development studio (visual studio 6.0), and identical code for both machines. The x64 machine has a Pentium E5400, the x86 machine has a pentium 4 dual core. Could this be an example of Deterministic Lockstep?.
I know this is vague - I wish I could provide some code, but there's over 1 million lines. All of the variables are REAL*4 and are calculated in the Fortran code several hundred times per second. The c++ MFC code assembles it into the executive.
Introduction
The difference you are observing are (probably) due to the fact that your executable includes optimized floating-point instructions, and the result of these instructions can be different between different architectures.
Enable float-point consistency
Note: The following only applies to older (6.0) versions of msvc++.
Unless you explicitly tell the compiler that you don't want it to optimize floating-point operations (where the trade-off might be some slight inaccuracy), it will do so.
Passing /Op as a flag to the compiler enables the "'consistency' floating-point model"; effectively disabling the previous mentioned optimization.
msdn.microsoft.com - VS6.0 - /Op (Improve Float Consistency)
The equivalent flag, /fp:strict, is the default option in VS2008.
Turn off SSE2
Note: The following only applies to newer versions of msvc++.
Unless you explicitly say that you don't want the msvc++ to generate SSE{,2} instructions for your floating-point calculations, such will be included in your executable.
You can force the compiler to disable generation of SSE and SSE2 instructions by passing the flag /arch:IA32 to it.
msdn.microsoft.com - /arch (x86)
Related
Suppose we take a compiled language, for example, C++. Now let's take an example Framework, suppose Qt. Qt has it's source code publically available and has the options for users to download the binary files and let users use their API. My question is however, when they compiled their code, it was compiled to their specific HardWare, Operating System, all that stuff. I understand how many Software Require recompilation for different types of Operating Systems (Including 32 vs 64bit) and offer multiple downloads on their website, however how does it not go even further to suggest it is also Hardware Specific and eventually result in the redistribution of compiled executes extremely frustrating to produce?
Code gets compiled to a target base CPU (e.g. 32-bit x86, x86_64, or ARM), but not necessarily a specific processor like the Core i9-10900K. By default, the compiler typically generates the code to run on the widest range of processors. And Intel and AMD guarantee forward compatibility for running that code on newer processors. Compilers often offer switches for optimizing to run on newer processors with new instruction sets, but you rarely do that since not all your customers have that config. Or perhaps you build your code twice (once for older processors, and an optimized build for newer processors).
There's also a concept called cross-compiling. That's where the compiler generates code for a completely different processor than it runs on. Such is the case when you build your iOS app on a Mac. The compiler itself is an x86_64 program, but it's generating ARM CPU instruction set to run on the iPhone.
Code gets compiled and linked with a certain set of OS APIs and external runtime libraries (including the C/C++ runtime). If you want your code to run on Windows 7 or Mac OSX Maverics, you wouldn't statically link to an API that only exists on Windows 10 or Mac OS Big Sur. The code would compile, but it wouldn't run on the older operating systems. Instead, you'd do a workaround or conditionally load the API if it is available. Microsoft and Apple provides the forward compatibility of providing those same runtime library APIs to be available on later OS releases.
Additionally Windows supports running 32-bit processes on 64-bit chips and OS. Mac can even emulate x86_64 on their new ARM based devices coming out later this year. But I digress.
As for Qt, they actually offer several pre-built configurations for their reference binary downloads. Because, at least on Windows, the MSVCRT (C-runtime APIs from Visual Studio) are closely tied to different compiler versions of Visual Studio. So they offer various downloads to match the configuration you want to build your your code for (32-bit, 64-bit, VS2017, VS2019, etc...). So when you put together a complete application with 3rd party dependencies, some of these build, linkage, and CPU/OS configs have to be accounted for.
So, here is what I am trying to accomplish. In my C++ project that has to be compiled with Microsoft Visual Studio 2015 or above, I need to have some code have different versions depending on the newest SIMD instrunction set available in the CPU of the user, among: SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512.
Since what I am look for at this point is compile-time CPU dispatching, my first guess was that it could be easily accomplished using compiler macros. However, to my astonishment, it has been quite hard to find information on how to achieve such CPU dispatching with macros in VS2015.
For instance, the former question "Detect the availability of SSE/SSE2 instruction set in Visual Studio" has information on how to detect SSE and SSE2 for x86 code, but not for x64 code. Although, they make a reference to this Microsoft's document: http://msdn.microsoft.com/en-us/library/b0084kay.aspx
There, we only have information on how to detect whether SSE, SSE2, AVX and AVX2 are enabled in the compiler - not exactly whether they are supported by CPU. Also, there is nothing at all about the other instrunction sets, like SSE3, SSSE3, SSE4.1, SSE4.2 and AVX512.
So, my question becomes: how can I detect whether the user's CPU supports those instrunction sets via macro, just like other compilers do, but with Microsoft Visual Studio 2015?
The problem you're facing is that Visual Studio historically is intended for software vendors. The idea that you compile your own software simply isn't in Microsoft's DNA.
The practical result is that Microsoft hardly cares about the processor of the build machine. That's unlikely to be the processor used to run the software.
On the upside, this also means that Microsoft doesn't suffer from the perennial Linux problem that the build system libraries are assumed to be present on the target machine. Building on Windows 10 for Windows 7 just works.
The compiler also doesn't allow you to enable up to SSE4.1, for example. You can only use /arch:avx or nothing. Also, that option only defines __AVX__, not the usual macros like __SSSE3__ that gcc/clang/icc define to indicate target support for previous instruction sets implied by AVX.
I always had these questions in my mind before I start learning C++:
1- Could an application that is compiled on a x86 computer run on a x64 computer?
2- Could an application that is compiled on a x64 computer run on a x86 computer?
3- Is there any difference?
4- If 1 and 2 are yes, Then why some applications have different downloads for each os bits, and why some libs I got like lua52 has a x64 and x86 version which work on the specified os only and errors on different os?
EDIT:
5- Can I compile my applications in x86 if my os is x64?
Ok, let's try and address those points in turn
Yes, an x86 computer could cross compile to x64 code (this is a common practice). Also the x64 based operating system may have an emulation layer for running x86 code (This is what Windows does for backwards compatibility)
Yes, a x64 computer could cross compile to x86 code (also a common practice). In theory, a x86 based operating system could have an emulation layer for running x64 code (though I don't believe this is done in practice)
In the case of cross compilation, there'll be no difference between a x64 code compiled on an x64 computer vs the same code cross compiled on a x86 computer. If the x64 is running an emulation layer to run x86 code, then it'll be less efficient than running native x64 code. If you want to support x86 systems, then you'll have to provide an x86 version.
See (3) - It's generally better better to provide 'native' versions.
Yes. - see (1) and (2)
note:before down vote or anything like this,this is a general question to understand more how everything is going
the question simply is:
assume I compiled a program with c++11 features (using VS2012 on windows) is there a guarantee that this program will run on older processors?(like core 2 duo;as most laptops got this)
I'm currently working with VS2010,but found libraries that needs C++11 features.
so I want to port the whole work to VS2012,but my knowledge is limited about how this gonna work
correct anything wrong in the question
edit:
another 2 questions:
1 -can I "mix" a compiled c++11 program with older one?
like calling functions which are inside the new version (.dll) from an old version(.exe) so I got 2 files:
1 is compiled with VS2010 the other 1 is compiled with VS2012,with DLL EXPORT can they work like that?
2 -suggest a better environment than VS2012 for windows
As long as the architecture for which the target is built is the same (x86 for 32 bits or amd64 for 64 bits) you shouldn't have any issue.
Of course you will need to provide the older machine with the correct runtime library to run your program (for the current architecture).
Yes, The compiler requires additional libraries to build the program. But this shouldn't affect the ability to run on older processors. The only time this changes is when your trying to run a 64 bit program on a 32 bit processor.
Porting to VS2012 is simple, open the solution in VS2012, and save it as a vs2012 solution. It should all be fine.
Edit: odds are, if your new to programming, all of your programs are compiled for 32 bit processors by default unless you code to change this, so you shouldn't worry. You can run 32 bit programs on 64 bit processors, just not the other way around. If you really want to step it up, you can make a program that can run on both processors ;)
given a compiled executable the usual requirements to run it are:
ABI
platform
libraries
and since Windows is a commercial product, depending on what are you doing, you could add another factor
environment
which means that sometimes a software house intentionally breaks the compatibility with other products to sell more stuff.
In general VS it's not that good, certainly it's not the best the compiler I have ever used and basically anything from GCC to Clang to MinGW can supersede VS easily, but VS it's the official compiler and environment for Windows so this is what you have to deal with most of the time.
If you have fulfilled the listed requirements you are good to go.
By the way a Core 2 Duo it's not that old, and the actual iCore generation it's not that different either.
It is said that by using C/C++, one can write 'native' programs - that run on the platform. I am confused about what is considered native - the processor architecture or the OS version?
For example:
I have a 32 bit processor and Windows 7 ( 32 bit ), and I compile and generate and .exe file. Is it guaranteed to run on any Windows 7 32 Bit? ( Win 7 32 bit on 32/64 Bit machines )
Edit1:
I did not intend only Windows OS here. My example can be extended to Linux also. For example, generating an executable ( by default a.out ) on a 32 bit Linux OS running on 32 bit processor, and then running it on a 32bit Linux on a 64 bit processor.
Edit2:
Thanks for the responses, but I also intended that I am using the standard libraries and functions - nothing OS Specific. Just the once specified by the ANSI or ISO C++ Standard. No references to OS specific windowing systems or other libraries.
Thanks
Both; kind of.
The actual instructions don't really differ across Windows and Linux as they are compiled down for a single CPU architecture (x86).
However, a binary is more than just code that runs on bare hardware. For instance, it also contains information that tells the operating system how to load the executable and its dependencies. The binary is packaged in a specific format. This format can be different in different operating systems.
Besides that, the operating system provides some services to the applications (through system calls and APIs). The services that operating systems provide, and the way they can be used varies from an operating system to another.
These reasons contribute to the fact that most of the time a native binary depends on both OS and CPU architecture it's compiled for.
Answer to the updated question:
C++ Standard doesn't require anything about the nature of the compiled target. It just specifies compatibility requirements at the source level. Consequently, if you stick to the standard libraries, you'll be able to use the same source code to compile on platforms that offer a conforming C++ implementation. The standard doesn't say anything about binary portability. As I mentioned above, the primitive system calls that operating systems provide can vary and the actual implementation of the standard library depends on the way those system calls are provided by the OS.
In order to run a Windows binary on Linux, you need to use some sort of emulation like Wine which understands Windows binary format and simulates Windows API for applications.
1) The processor architecture (plus the targeted libraries static or dynamic)
2) Yes
A 32bit windows application will run on a Windows 64bit platform as WOW.
If your (windows) compiler's target architecture is x86 (32-bit) then it can run on any 32 bit and 64 bit Windows 7. But if its x86-64, it will only run on 64 bit Windows 7.
To answer the title specifically, you code for both.
The executable contains machine code, which is specific to the processor, and a lot of metadata for the OS on how to load/execute the program, which is specific to the OS.
The code may also (and typically does) contain calls into functions defined by the OS. And so, while it is just perfectly ordinary machine code that any compatible CPU will understand, it attempts to call code that only exists on Windows.
So "native" really means both. You code for the specific OS (and all compatible OS'es) and that specific CPU (and all compatible CPUs).
In the case of Windows, you typically target a specific version of Windows, and the program will then work on that, and future versions of Windows.
for the processor on which Windows (and your program) runs, the executable contains x86 machine code, which can be executed on any x86 CPU, whether it is from Intel, AMD, Via or whoever else have made compatible processors over the years.
Without being able to see your code, only you can tell us whether you're coding for 32-bit or 64-bit platform - for example, if you reinterpret_cast a pointer into a 32 bit int then back to a pointer, you are coding for 32-bit, whereas if you use a type such as int_ptr you are safe whether your code is compiled for 32 or 64 bit machines. Similarly, coding for Windows desktops your coding can assume the machine's endianess.
If, as in your example, you compile that code for 32-bit Windows 7, then it will also run on 64 bit Windows 7. If you use Windows 7 features, it won't run on earlier versions. Microsoft are very good at backward compatibility, so it probably will run on later versions.
Short answer: No.
Longer: When you compile "native code", you compile for a specific processor architecture; MIPS, ARM, x86, 68k, Sparc and so on. These architectures can have a wordlength of 8, 16, 32 and 64 (there are exceptions). Also these architectures can have extensions from generation to generation like MMX, SSE, SSE2, Neon and such.
Also you need to consider the operating system and what libraries you can use, and different calling conventions.
So, there's no guarantee. But if you compile with MSVC on Windows 7 it's almost guaranteed to run on Windows 7. I think it only exist for x86 at the moment.