packages feed

cuda-0.7.5.2: cbits/init.c

#include "cbits/stubs.h"
#include <stdio.h>

/*
 * Make sure that the linker always touches this module so that it notices the
 * below constructor function. Calling this empty function as part of
 * 'Foreign.CUDA.Driver.initialise' should be sufficient to prevent it from ever
 * being stripped.
 */
void enable_constructors() { }

/*
 * GHC-8 introduced a new (simpler) 64-bit allocator, which on startup 'mmap's
 * 1TB of address space and then commits sub-portions of that memory as needed.
 *
 * The CUDA driver also appears to 'mmap' a large chunk of address space on
 * 'cuInit', probably as the arena for shuffling memory to and from the device,
 * but attempts to do so at a _fixed_ address. If the GHC RTS has already taken
 * that address at the time we call 'cuInit', driver initialisation will fail
 * with an "out of memory" error.
 *
 * The workaround is to call 'cuInit' before initialising the RTS. Then the
 * RTS's allocation will avoid CUDA's allocation, since the RTS doesn't care
 * where in the address space it gets that memory. Embedding the following
 * __attribute__((constructor)) function in the library does the trick nicely,
 * and the linker will ensure that this gets executed when the shared library is
 * loaded (during program startup).
 *
 * Another way around this, without actually calling 'cuInit', would be to just
 * reserve the regions that 'cuInit' requires in the constructor function so
 * that the RTS avoids them, then release them before calling 'cuInit'. However,
 * since the CUDA driver is closed and we don't know exactly which regions to
 * reserve, that approach would be fragile.
 *
 * See: https://github.com/tmcdonell/cuda/issues/39
 */
#ifdef CUDA_PRELOAD
__attribute__((constructor)) void preinitialise_cuda()
{
    CUresult status = cuInit (0);

    if ( status != CUDA_SUCCESS ) {
#if CUDA_VERSION >= 6000
        const char* str = NULL;

        cuGetErrorString(status, &str);
        fprintf(stderr, "Failed to pre-initialise CUDA: %s\n", str);
#else
        fprintf(stderr, "Failed to pre-initialise CUDA (%d)\n", status);
#endif
    }
}
#endif