64bit atomicAdd in CUDA - c++

I have a problem using atomicAdd under CUDA 7. atomicAdd is defined for "int", "unsigned int" and "unsigned long long int" stating it uses "the 32 or 64 bit value".
In our code we use uint32_t and uint64_t for safety. However gcc defines this in the following way:
#if __WORDSIZE == 64
typedef unsigned long int uint64_t;
#else
__extension__
typedef unsigned long long int uint64_t;
#endif
So when I pass an uint64_t to atomicAdd it complains because it is not defined for "unsigned long int".
Is it save to assume uint64_t == long long int for CUDA compilation as stated in the programming guide?

To answer that for future reference:
There are 2 options: Either use a typedef to define 64 bit cuda types like:
typedef long long int int64_cu
typedef unsigned long long int uint64_cu
And probably guard these by (boost-)static_asserts to be the same size(of)
Or as suggested by #Anastasiya Asadullayeva use a reinterpret_cast in the call which is better also guarded by a static_assert.

Related

Seemingly compiler-specific failure to convert 64 bit bitset to binary string representation

Here is my code:
#include<iostream>
#include<string>
#include<bitset>
using namespace std;
int main()
{
long long int number;
number = 123456789123456789;
string binary = bitset<64>(number).to_string();
cout<<binary<<"\n";
return 0;
}
Here is the result: 0000000000000000000000000000000010101100110100000101111100010101 but it's wrong.
Info from comments (and OPs experiment):
Same code results in expected binary representation in other environments.
What is the reason?
I can reproduce the problem under the following circumstances:
32-bit target architecture,
either old GCC version or compilation against C++03.
For example, with GCC 10.2, this happens with -m32 -std=c++03, with GCC 4.9.2 just with -m32. Until C++11, there was no unsigned long long defined by the standard. Though C++98/03 implementations may provide it as a non-standard extension, the parameter of the constructor of std::bitset was of unsigned long type only. Which, in the above-described cases, is only 32-bit long. This is where you lost the upper bits.
Live demo: https://godbolt.org/z/PWdY8K
The relevant part in libstdc++ is here:
#if __cplusplus >= 201103L
constexpr bitset(unsigned long long __val) noexcept
: _Base(_Sanitize_val<_Nb>::_S_do_sanitize_val(__val)) { }
#else
bitset(unsigned long __val)
: _Base(__val)
{ _M_do_sanitize(); }
#endif

what is the type of unsigned integers in c?

uint8 can be represented as ubyte, uint16 can be represented as is uword, uint32 can be represented as ulong, uint64 can be represented as ?
I am searching regarding how the unsigned integers can be represented as data type in c but I got confusion to how to present uint64 ??
Is it possible to use uint64 as udouble in c ?? please someone guide me ??
Will it support ??
what could be the format specifiers for all the above ??
I am simply adding this line because it is asking that the body does not meet the requirement and telling to add some content. So I added this.
All these types uint8, uint16, uint32, uint64 are not standard fundamental types and they are either typedef names or implementation defined types
As for uint64 then it can be defined for example as
typedef unsigned long long uint64;
Take into account that sizes of integral types are implementation defined. So it could be that in the definition above it is enough to use unsigned long because on some platform sizeof( unsigned long) can be equal to 8 bytes.
If you want to use standard integral types that do not depend on used platform then you should include header <cstdint>
There are the following unsigned type definitions among other defined types
typedef unsigned integer type uint8_t; // optional
typedef unsigned integer type uint16_t; // optional
typedef unsigned integer type uint32_t; // optional
typedef unsigned integer type uint64_t; // optional
typedef unsigned integer type uint_fast8_t;
typedef unsigned integer type uint_fast16_t;
typedef unsigned integer type uint_fast32_t;
typedef unsigned integer type uint_fast64_t;
typedef unsigned integer type uint_least8_t;
typedef unsigned integer type uint_least16_t;
typedef unsigned integer type uint_least32_t;
typedef unsigned integer type uint_least64_t;
#include <stdint.h>
to get all types defined in global namespace.
#include <cstdint>
to get it defined in namespace std.
On my implementation i.e. in stdint.h I can find:
#if __WORDSIZE == 64
typedef unsigned long int uint64_t;
#else
__extension__
typedef unsigned long long int uint64_t;
#endif
and for uint32_t:
#ifndef __uint32_t_defined
typedef unsigned int uint32_t;
# define __uint32_t_defined
#endif

c++ cross platform way to define 64bit unsigned integer

Right now I'm working on a project that extensively uses 64bit unsigned integers in many parts of the code. So far we have only been compiling with gcc 4.6 but we are now porting some code to windows. It's crucial that these unsigned ints are 64bits wide. It has been suggested that we could use long long but it's not good if long long happens to be bigger than 64bits, we actually want to have a guarantee that it will be 64 bits and writing something like static_assert(sizeof(long long) == 8) seems to be a bit of a code smell.
What is the best way to define something like uint64 that will compile across both gcc and msvc without needing to have different code syntax used everywhere?
What about including cstdint and using std::uint64_t?
You can use boost:
The typedef int#_t, with # replaced by the width, designates a signed
integer type of exactly # bits; for example int8_t denotes an 8-bit
signed integer type. Similarly, the typedef uint#_t designates an
unsigned integer type of exactly # bits.
See: http://www.boost.org/doc/libs/1_48_0/libs/integer/doc/html/boost_integer/cstdint.html
Especially this header:
http://www.boost.org/doc/libs/1_48_0/boost/cstdint.hpp
This is what I do:
#ifndef u64
#ifdef WIN32
typedef unsigned __int64 u64;
#else // !WIN32
typedef unsigned long long u64;
#endif
#endif
On Windows you can use __int64, unsigned __int64, or typedefs: UINT64, INT64 etc.
Look at this
But yes, if code portability is concern, use standard typedefs, as suggested by others.

C++ U32 type header

I want to use U32 type but I can't find the header where it is defined. Does anyone know?
There is no standard type called U32, but if you #include <cstdint> (stdint.h for C) you can use std::uint32_t1, a 32 bit unsigned integer, which is (I assume) what you want.
Here is a list of types in the cstdint header:
namespace std {
int8_t
int16_t
int32_t
int64_t
int_fast8_t
int_fast16_t
int_fast32_t
int_fast64_t
int_least8_t
int_least16_t
int_least32_t
int_least64_t
intmax_t
intptr_t
uint8_t
uint16_t
uint32_t
uint64_t
uint_fast8_t
uint_fast16_t
uint_fast32_t
uint_fast64_t
uint_least8_t
uint_least16_t
uint_least32_t
uint_least64_t
uintmax_t
uintptr_t
}
1 Thanks Martinho Fernandes for pointing out that these types are in the namespace std.
While cstdint might be a solution, it's not universal -- MSVC versions before 2010 didn't ship with that one. If writing for multiple platforms you'll need to supply the standard types yourself if MSVC < 2010 is detected. Or use the boost one if you use boost.
U32 is an idiomatic shortcut for an unsigned int. Its common definition is:
typedef unsigned int U32;
But the main reason for its use is to be able to control the actual definition manually. Hope this helps.

Is there long long defined?

Where to check if type long long is defined? I wanna do something like this:
#ifdef LONGLONG
#define long_long long long
#else
#define long_long long
#endif
LLONG_MAX gives the maximum value representable by a long long; if your implementation doesn't support long long, it shouldn't define LLONG_MAX.
#include <limits.h>
#ifdef LLONG_MAX
#define long_long long long
#else
#define long_long long
#endif
This isn't a perfect solution. long long isn't standard in C++03, and long long has been around longer than C99, so it's possible (and likely) that a compiler could support long long but not define LLONG_MAX.
If you want an integer type with a specific size, you should use <stdint.h> if your implementation supports it. If your implementation doesn't support it, Boost has an implementation of it.
Rather than worry about whether or not a type with that name is defined, I'd #include <climits> and check whether or not you can find an integer type large enough for your intended use. (Although you could probably just check if LLONG_MAX is defined to find out if long long exists.)
Edit: Or, if you can assume C99 headers and types to be available, #include <cstdint.h> and use e.g. int64_t to get a 64-bit type or int_fast64_t to get a “fast” 64-bit type (by some compiler-specific definition of fast). Or intmax_t if you want the largest available type.