0

I have a CUDA kernel function that accepts a uint8_t*. I want to write a calculated float to a specific position in this uint8_t* array (12 bytes after the pointer start position).

What would be the proper way of doing this? If I assume:

uint8_t* ptr = address of a properly initialized and allocated memory segment

Then the following causes the kernel to crash:

float some_float = ...
*((float *) (ptr+12)) = some_float

I know this is probably not the proper way of doing this, maybe even a faux-pas to some... But maybe someone can give a tip or two about how to best go about this.

Thanks!

Marc
  • 1
  • 1
  • Tested it - it shouldn't crash if the array is properly initialized. This short code doesn't crash and outputs right result: `float num; uint8_t arr[4]; uint8_t* ptr = &arr[0]; num = 14; *((float*)(ptr)) = num; num = *((float*)(ptr));` – xinaiz Jun 29 '16 at 22:41
  • Please provide a [MCVE](https://stackoverflow.com/help/mcve). – Xiobiq Jun 29 '16 at 22:41
  • There is the possibility of alignment problems if `ptr` doesn't point to a nice, divisible by `sizeof(float)` address, but I join the crowd calling for a [mcve]. – user4581301 Jun 29 '16 at 22:43
  • 1
    why is the question titled "Writing a float to a void* location" ? I don't see that concept expressed anywhere. You want to write a `float` to a specific position in a `uint8_t` array. CUDA requires that all writes from device code to device memory be [naturally aligned](http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#device-memory-accesses). You can't satisfy the natural alignment requirement by writing a `float` to an arbitrary position indexed from an arbitrary `uint8_t*` pointer. You would have to know something about the underlying alignment of the `uint8_t*` pointer. – Robert Crovella Jun 29 '16 at 22:59

1 Answers1

-2

How do you write the float value ?

I already work on a project that handle multiple object with different data size. We want to keep the object properties in a chain list but stored data in a single common big buffer. So in this buffer we have 8-bit signed integer, followed by a 32-bit float, followed by an unsigned integer 64 bit, etc ... obviously except the first element no one was aligned to save space. So when we want to write a value we do :

// Write float value to any position in your big buffer
float fValueToWrite = 10;
memcpy(ptr + 12, &fValueToWrite, sizeof(fValueToWrite));

When we want to read the value we do :

// Read the float from any unalign position of your big buffer
float fReadValue = 0;
memcpy(&fReadValue, ptr + 12, sizeof(fReadValue));

The trick is using memcpy that don't care about reading from a non word boundary.

But if we did this to read :

float buffer[256] = {0};`
uint8_t* ptr = (uint8_t *)buffer; 
float fCrashReadValue = *((float *)(ptr + 11));

may cause alignment fault on processor that do not support reading from boundary divisible by 11 (LoL indeed it's a prime number). Thus, if your CPU is 32 bits in this case 12 is a valid boundary as long as ptr is pointing to the allocated buffer and not on another pointer that may not be properly aligned.

By experience I can told your that many ARM processor that I worked with will fault using a non-boundary address. But x86 (intel) processor will quietly realign with a penalty performance.

Hope it will help you :)

erakis
  • 60
  • 3
  • 12
  • I see come correctness in there, `memcpy` is a nice, safe way to pull this off, but the rest is either poorly worded, mistaken, or a combination of the two. – user4581301 Jun 29 '16 at 22:47