A simple question: do longs differ from architecture to architecture? I seem to recall a while back that when we went from a 32-bit machine to a 64-bit machine, the longs might differ, but as I check things now, they appear to be the same (a 64-bit integer, effectively).
I ask, because I am writing some code, which speccs in Int64s (C#), and while longs and Int64s appear to be the same at the moment, the damn autocomplete likes using longs instead of Int64s, which it sees as the same. To save myself from time, should I let it autocomplete with longs, and sleep soundly because they won't be changing if someone comes out with a 128-bit CPU tomorrow, or should I put forth the extra effort now to ensure that they are Int64s in said code? And yes, I am aware that Int64 = long, so far as the current implementation cares.
While in C the size of long may vary, it is well specified in C# to be 64bit integer.
Related
I've been developing a game in C# which currently uses floating points for some calculations and arithmetic. This game will feature networking functionality and a basic replay system which keeps track of inputs and basic player actions over time. I think these features require me to have every important core mechanic be deterministic. Due to the supposed indeterministic attributes of floating point numbers, I have gone through some resources about fixed-point numbers in order to provide myself with an alternative to floating point.
I understand many of the core concepts of fixed-point due to a variety of very well documented online resources on the matter. However, I'm unsure of whether or not I should use a 32bit type (int) or 64bit type (long) for the raw-value of the fixed-point class.
I would like to have the following basic features for my class:
Pass a float, double or int and convert it to a fixed-point value.
Addition, Subtraction, Division, Multiplication against values of types fixed-point, int, float and double.
My assumption is that it would be best to use a long as it will give me more decimal accuracy, but I am worried about potential roadblocks that may come along the way. For example, would using a long provide issues when targeting 32bit or running on 32bit machines? Are ints ultimately more compatible than long when it comes to potential hardware configurations? Because games are performance heavy, is there a large performance loss when switching from float to long based fixed-point numbers?
It seems like a silly question, but I guess I'm wondering if I should use types based off the lowest common denominator of cpu architecture that I expect my program to run on or are these concerns typically handled by the compiler during compilation? Will linux or mac osx handle long calculations differently than a windows machine?
The type you use is irrelevant, with regards to the platform, as types are types are types, in C#. In other words, a long is always 64 bits, no matter what platform you're on. It's a guarantee of C#.
However, the real problem is going to be precision and scale.. When doing fixed-point math, you're going to have to pick the precision you want to use. That's an easy problem. What's not easy is scaling. If you have numbers that will exceed the maximum value of your chosen type (don't forget to include the decimals in this consideration), then you're broken out of the gate.
Have you looked into the decimal type?
decimal is still a floating-point type, but it is floating-point decimal, rather than IEEE754 binary floating-point, and thus is capable of representing any base-10 number you throw at it, so long as it fits in the scale and precision of the decimal type.
See these links for information on the decimal type:
C# In Depth:Decimal
MSDN C# decimal reference
decimal comes with some performance considerations, however, and may not be the best choice for a game, if performance is critical. For a simple 2D scroller, you'd be fine, but it's probably not ideal for anything beyond that.
The results will be exactly the same across all targets. Integer math is nice like that, you can really rely on it to be the same all the same time.
Using a long will be slower though, particularly when targeting 32bit machines but also on 64bit machines. While adding ints and adding longs takes the same time on a 64bit machine (if it's actually 64bit code), doing a fixpoint multiplication requires some extra code if you don't have a type that's twice as big. 64bit division has the same problem. Of course on 32bit machines, 64bit operations are emulated using multiple 32bit operations, so they are inherently slightly slower there.
On the other hand, you may need the extra precision sometimes. In the end you may need both a 32bit fixpoint type and a 64bit one, or even multiple of those with differently positioned radix points.
I have a function in C# that returns the following:
...
float amount = smallestPercentage * (float)quantity;
return (int)amount;
Now I know I am suppose to use Convert.Int32(amount) rather than type cast an int, and that has fixed the problem. But my problem was really this...
When developing my program at home (Windows Vista) I would get a return value of 1, but when a deployed the program to another environment (Windows XP), I would get a return value of 0.
I was wondering if this has to do with the Windows version, the .NET version or even the CPU processor?
Thanks.
David
In fact, you can get different results:
on different machines
depending on whether you compiled with debug or retail build settings
depending on whether you did the math in compile-time constants or runtime values
how local variables and other temporary values are used in your method
and so on.
The C# specification calls out that floating point arithmetic may be done in higher precision than you expect. It's never done in lower precision than you'd expect, but we reserve the right to use higher-precision algorithms on certain hardware and with certain optimizations available, any time the jitter thinks that it can get away with it. That means that in operations that are highly sensitive to small changes in precision -- like rounding -- can give very different results seemingly without explanation.
You are not the first Stack Overflow user to discover this fact: Problem converting from int to float
When dealing with floating point numbers its really advisable that you use some sort of rounding routine. In C#, I believe the best approach is the Math.Round method.
As to why its happening, different processors have different routines for computing floats and doubles. On your target machine you're likely getting a value slightly below 1 (say, .999987) that when casted gets turned into 0. Floats have been around since the CLR was created, so this is most likely a processor specific thing. OSes very rarely interfere with direct application code.
I am wondering about the performance of different primitive types, primarily in C#. Now, I realize this is not strictly a language related concept, since the machine is optimized for handling types.
I have read the following two questions:
performance of byte vs. int in .NET
Why should I use int instead of a byte or short in C#
Nevertheless, I need a few clarifications.
I know that on a 32-bit machine an int is faster than both short and byte, since int is native for the platform. However, what happens on 64-bit systems? Is it better, performance wise, to use a long instead of an int?
Also, what happens with floating point types? Is double better than float?
The answer may or may not be language specific. I assume there aren't many differences for different languages regarding this issue. However, if there are, it would be nice to have an explanation of why.
Actually in most cases you will get the same performance in anything smaller than your machines architecture (i.e. int, short, byte on 32 bit) as internally the code will just use a 32 bit value to process them.
The same applies on 64 bit systems, there is no reason not to use an int (as they will run at the same speed as a long on 64 bit, faster than a long on 32 bit) unless you need the extra range. If you think about it - 64 bit systems had to run 32 bit code fast as otherwise no-one would have made the transition.
The smaller size is only used when packing multiple copies of the primitive into structures such as arrays. There you do get a small slowdown from unpacking them, but in most cases that will be more than compensated for by things such as better cache/memory coherence.
In 10, or even 5 years there will be no [Edit2: server or desktop] 32-bit CPUs.
So, are there any advantages in using int (32bit) over long (64bit) ?
And are there any disadvantages in using int ?
Edit:
By 10 or 5 years I meant on vast majority of places where those langs are used
I meant which type to use by default. This days I won't even bother to think if I should use short as cycle counter, just for(int i.... The same way long counters already win
registers are already 64-bit, there is already no gain in 32 bit types. And I think some loss in 8 bit types (you have to operate on more bits then you're using)
32-bit is still a completely valid data type; just like we have 16-bit and bytes still around. We didn't throw out 16-bit or 8-bit numbers when we moved to 32-bit processors. A 32-bit number is half the size of a 64-bit integer in terms of storage. If I were modeling a database, and I knew the value couldn't go higher than what a 32-bit integer could store; I would use a 32-bit integer for storage purposes. I'd do the same thing with a 16-bit number as well. A 64-bit number takes more space in memory as well; albeit not anything significant given today's personal laptops can ship with 8 GB of memory.
There is no disadvantage of int other than it's a smaller data type. It's like asking, "Where should I store my sugar? In a sugar bowl, or a silo?" Well, that depends on entirely how much sugar you have.
Processor architecture shouldn't have much to do with what size data type you use. Use what fits. When we have 512-bit processors, we'll still have bytes.
EDIT:
To address some comments / edits..
I'm not sure about "There will be no 32-bit desktop CPUs". ARM is currently 32-bit; and has declared little interest in 64-bit; for now. That doesn't fit too well with "Desktop" in your description; but I also think in 5-10 years the landscape of the type of devices we are writing software will drastically change as well. Tablets can't be ignored; people will want C# and Java apps to run on them, considering Microsoft officially ported Windows 8 to ARM.
If you want to start using long; go ahead. There is no reason not to. If we are only looking at the CPU (ignoring storage size), and making assumptions we are on an x86-64 architecture, then it doesn't make much difference.
Assuming that we are sticking with the x86 architecture; that's true as well. You may end up with a slightly larger stack; depending on whatever framework you are using.
If you're on a 64-bit processor, and you've compiled your code for 64-bit, then at least some of the time, long is likely to be more efficient because it matches the register size. But whether that will really impact your program much is debatable. Also, if you're using long all over the place, you're generally going to use more memory - both on the stack and on the heap - which could negatively impact performance. There are too many variables to know for sure how well your program will perform using long by default instead of int. There are reasons why it could be faster and reasons why it could be slower. It could be a total wash.
The typical thing to do is to just use int if you don't care about the size of the integer. If you need a 64-bit integer, then you use long. If you're trying to use less memory and int is far more than you need, then you use byte or short.
x86_64 CPUs are going to be designed to be efficient at processing 32-bit programs and so it's not like using int is going to seriously degrade performance. Some things will be faster due to better alignment when you use 64-bit integers on a 64-bit CPU, but other things will be slower due to the increased memory requirements. And there are probably a variety of other factors involved which could definitely affect performance in either direction.
If you really want to know which is going to do better for your particular application in your particular environment, you're going to need to profile it. This is not a case where there is a clear advantage of one over the other.
Personally, I would advise that you follow the typical route of using int when you don't care about the size of the integer and to use the other types when you do.
Sorry for the C++ answer.
If the size of the type matters use a sized type:
uint8_t
int32_t
int64_t
etc
If the size doesn't matter use an expressive type:
size_t
ptrdiff_t
ssize_t
etc
I know that D has sized types and size_t. I'm not sure about Java or C#.
In my C# app, I would like to know whether it is really important to use short for smaller numbers, int for bigger etc. Does the memory consumption really matter?
Unless you are packing large numbers of these together in some kind of structure, it will probably not affect the memory consumption at all. The best reason to use a particular integer type is compatibility with an API. Other than that, just make sure the type you pick has enough range to cover the values you need. Beyond that for simple local variables, it doesn't matter much.
The simple answer is that it's not really important.
The more complex answer is that it depends.
Obviously you need to choose a type that will hold your datastructure without overflowing, and even if you're only storing smaller numbers then choosing int is probably the most sensible thing to do.
However, if your application loads a lot of data or runs on a device with limited memory then you might need to choose short for some values.
For C# apps that aren't trying to mirror some sort of structure from a file, you're better off using ints or whatever your native format is. The only other time it might matter is if using arrays on the order of millions of entries. Even then, I'd still consider ints.
Only you can be the judge of whether the memory consumption really matters to you. In most situations it won't make any discernible difference.
In general, I would recommend using int/Int32 where you can get away with it. If you really need to use short, long, byte, uint etc in a particular situation then do so.
This is entirely relative to the amount of memory you can afford to waste. If you aren't sure, it probably doesn't matter.
The answer is: it depends. The question of whether memory matters is entirely up to you. If you are writing a small application that has minimal storage and memory requirements, then no. If you are google, storing billions and billions of records on thousands of servers, then every byte can cost some real money.
There are a few cases where I really bother choosing.
When I have memory limitations
When I do bitshift operations
When I care about x86/x64 portability
Every other case is int all the way
Edit : About x86/x64
In x86 architecture, an int is 32 bits but in x64, an int is 64 bits
If you write "int" everywhere and move from one architecture to another, it might leads to problems. For example you have an 32 bits api that export a long. You cast it to an integer and everything is fine. But when you move to x64, the hell breaks loose.
The int is defined by your architecture so when you change architecture you need to be aware that it might lead to potential problems
That all depends on how you are using them and how many you have. Even if you only have a few in memory at a time - this might drive the data type in your backing store.
Memory consumption based on the type of integers you are storing is probably not an issue in a desktop or web app. In a game or a mobile device app, it may be more of an issue.
However, the real reason to differentiate between the types is the kind of numbers you need to store. If you have really big numbers, or high precision, you may need to use long to store it.
The context of the situation is very important here. You don't need to take a guess at whether it is important or not though, we are dealing with quantifiable things here. We know that we are saving 2 bytes by using a short instead of an int.
What do you estimate the largest number of instances are going to be in memory at a given point in time? If there are a million then you are saving ~2Mb of Ram. Is that a large amount of ram? Again, it depends on the context, if the app is running on a desktop with 4Gb of ram you probably don't care too much about the 2Mb.
If there will be hundreds of millions of instances in memory the savings are going to get pretty big, but if that is the case you may just not have enough ram to deal with it and you may have to store this structure on disk and work with parts of it at a time.
Int32 will be fine for almost anything. Exceptions include:
if you have specific needs where a different type is clearly better. Example: if you're writing a 16 bit emulator, Int16 (aka: short) would probably be better to represent some of the internals
when an API requires a certain type
one time, I had an invalid int cast and Visual Studio's first suggestion was to verify my value was less than infinity. I couldn't find a good type for that without using the pre-defined constants, so i used ulong since that was the closest I could come in .NET 2.0 :)