Beispiel #1
0
/**
 * \brief Returns a cuda context against the handle in the argument.
 *
 *        If a cuda_context is not present for a handle, it is created
 *        and associated with this handle and the context is returned
 *        in the argument.  If a cuda_context is already present for
 *        a handle, it is returned.
 *
 * \param p_context    Pointer to a cuda context instance that should be updated
 *                     with a cuda context.
 * \param cuda_profile The cuda profile, supplied as a string.
 * \param handle       A unique handle which identifies a module.  Obtained from
 *                     a call to SCCudaHlGetUniqueHandle().
 *
 * \retval  0 On success.
 * \retval -1 On failure.
 */
int SCCudaHlGetCudaContext(CUcontext *p_context, char *cuda_profile, int handle)
{
    SCCudaHlModuleData *data = NULL;
    SCCudaDevices *devices = NULL;

    if (p_context == NULL) {
        SCLogError(SC_ERR_INVALID_ARGUMENTS, "Error invalid arguments.  "
                   "p_context NULL");
        return -1;
    }

    /* check if the particular module that wants a CUDA context
     * is already registered or not.  If it is not registered
     * log a warning and get out of here */
    if ( (data = SCCudaHlGetModuleData(handle)) == NULL) {
        SCLogDebug("Module not registered.  You can't create a CUDA context "
                   "without registering a module first.  To use this "
                   "registration facility, first register a module using "
                   "SCCudaHlRegisterModule(), and then register "
                   "a cuda context with that module hanle using "
                   "SCCudaHlGetCudaContext(), after which you can call this "
                   "function ");
        return -1;
    }

    if (data->cuda_context != 0) {
        p_context[0] = data->cuda_context;
        return 0;
    }

    int device_id = SC_CUDA_DEFAULT_DEVICE;
    if (cuda_profile != NULL) {
        /* Get default log level and format. */
        MpmCudaConf *profile = SCCudaHlGetProfile(cuda_profile);
        if (profile != NULL) {
            if (SCCudaIsCudaDeviceIdValid(profile->device_id)) {
                device_id = profile->device_id;
            } else {
                SCLogError(SC_ERR_CUDA_ERROR, "Invalid device id \"%d\" supplied.  "
                           "Using the first device.", profile->device_id);
            }
        }
    }

    /* Get the device list for this CUDA platform and create a new cuda context */
    devices = SCCudaGetDeviceList();
    if (SCCudaCtxCreate(p_context, 0, devices->devices[device_id]->device) == -1)
        goto error;
    data->cuda_context = p_context[0];

    return 0;

 error:
    return -1;
}
CUcontext CudaHandlerModuleGetContext(const char *name, int device_id)
{
    SCMutexLock(&mutex);

    CudaHandlerModule *module = cudahl_modules;
    while (module != NULL && strcasecmp(module->name, name) != 0)
        module = module->next;
    if (module != NULL) {
        if (module->device_id != device_id) {
            SCLogError(SC_ERR_CUDA_HANDLER_ERROR, "Module already "
                       "registered, but the new device_id is different "
                       "from the already registered device_id.");
            exit(EXIT_FAILURE);
        }
        SCMutexUnlock(&mutex);
        return module->context;
    }

    CudaHandlerModule *new_module = SCMalloc(sizeof(CudaHandlerModule));
    if (new_module == NULL)
        exit(EXIT_FAILURE);
    memset(new_module, 0, sizeof(CudaHandlerModule));
    new_module->device_id = device_id;
    new_module->name = SCStrdup(name);
    if (new_module->name == NULL)
        exit(EXIT_FAILURE);
    if (cudahl_modules == NULL) {
        cudahl_modules = new_module;
    } else {
        new_module->next = cudahl_modules;
        cudahl_modules = new_module;
    }

    if (no_of_cuda_contexts <= device_id) {
        cuda_contexts = SCRealloc(cuda_contexts, sizeof(CUcontext) * (device_id + 1));
        if (cuda_contexts == NULL)
            exit(EXIT_FAILURE);
        memset(cuda_contexts + no_of_cuda_contexts, 0,
               sizeof(CUcontext) * ((device_id + 1) - no_of_cuda_contexts));
        no_of_cuda_contexts = device_id + 1;
    }

    if (cuda_contexts[device_id] == 0) {
        SCCudaDevices *devices = SCCudaGetDeviceList();
        if (SCCudaCtxCreate(&cuda_contexts[device_id], CU_CTX_SCHED_BLOCKING_SYNC,
                            devices->devices[device_id]->device) == -1) {
            SCLogDebug("ctxcreate failure.");
            exit(EXIT_FAILURE);
        }
    }
    new_module->context = cuda_contexts[device_id];

    SCMutexUnlock(&mutex);
    return cuda_contexts[device_id];
}
int CudaHandlerGetCudaModule(CUmodule *p_module, const char *ptx_image)
{
#define CUDA_HANDLER_GET_CUDA_MODULE_BUFFER_EXTRA_SPACE 15

    int i = 0;

    /* select the ptx image based on the compute capability supported by all
     * devices (i.e. the lowest) */
    char *image = SCMalloc(strlen(ptx_image) + CUDA_HANDLER_GET_CUDA_MODULE_BUFFER_EXTRA_SPACE);
    if (unlikely(image == NULL)) {
        exit(EXIT_FAILURE);
    }
    memset(image, 0x00, strlen(ptx_image) + CUDA_HANDLER_GET_CUDA_MODULE_BUFFER_EXTRA_SPACE);

    int major = INT_MAX;
    int minor = INT_MAX;
    SCCudaDevices *devices = SCCudaGetDeviceList();
    for (i = 0; i < devices->count; i++){
        if (devices->devices[i]->major_rev < major){
            major = devices->devices[i]->major_rev;
            minor = devices->devices[i]->minor_rev;
        }
        if (devices->devices[i]->major_rev == major &&
            devices->devices[i]->minor_rev < minor){
            minor = devices->devices[i]->minor_rev;
        }
    }
    snprintf(image,
             strlen(ptx_image) + CUDA_HANDLER_GET_CUDA_MODULE_BUFFER_EXTRA_SPACE,
             "%s_sm_%u%u",
             ptx_image, major, minor);

    /* we don't have a cuda module associated with this module.  Create a
     * cuda module, update the module with this cuda module reference and
     * then return the module refernce back to the calling function using
     * the argument */
    SCLogDebug("Loading kernel module: %s\n",image);
    if (SCCudaModuleLoadData(p_module, (void *)SCCudaPtxDumpGetModule(image)) == -1)
        goto error;
    SCFree(image);

    return 0;
 error:
    SCFree(image);
    return -1;

#undef CUDA_HANDLER_GET_CUDA_MODULE_BUFFER_EXTRA_SPACE
}
/**
 * \brief Returns a cuda_module against the handle in the argument.
 *
 *        If a cuda_module is not present for a handle, it is created
 *        and associated with this handle and the cuda_module is returned
 *        in the argument.
 *
 * \param p_module The loaded CUmodule that is returned.
 * \param ptx_image Name of the module source file, w/o the .cu extension
 * \param handle    A unique handle which identifies a module.  Obtained from
 *                  a call to SCCudaHlGetUniqueHandle().
 *
 * \retval  A unique handle within the module that is associated with the
 *          loaded CUmodule. Needed for future API calls.
 * \retval  -1 on failure.
 */
int SCCudaHlGetCudaModule(CUmodule *p_module, const char *ptx_image, int handle)
{
    SCCudaHlModuleData *data = NULL;
    SCCudaHlModuleCUmodule *new_module_cumodule = NULL;
    SCCudaHlModuleCUmodule *module_cumodules = NULL;

    if (p_module == NULL) {
        SCLogError(SC_ERR_INVALID_ARGUMENTS, "Error invalid arguments"
                   "p_module NULL");
        return -1;
    }

    /* check if the particular module that wants a CUDA module is already
     * registered or not.  If it is registered, check if a context has
     * been associated with the module.  If yes, then we can go ahead and
     * create a cuda module and associate it with the module referenced by
     * the handle in the functions arguments. If no, log warning and get
     * out of here */
    if ( ((data = SCCudaHlGetModuleData(handle)) == NULL) ||
         (data->cuda_context == 0)) {
        SCLogDebug("Module not registered or no cuda context associated with "
                   "this module.  You can't create a CUDA module without"
                   "associating a context with a module first. To use this "
                   "registration facility, first register a module using "
                   "context using SCCudaHlRegisterModule(), and then register "
                   "a cuda context with that module using "
                   "SCCudaHlGetCudaContext(), after which you can call this "
                   "function ");
        return -1;
    }

    /* Register new CUmodule in the module */
    new_module_cumodule = SCMalloc(sizeof(SCCudaHlModuleCUmodule));
    if (unlikely(new_module_cumodule == NULL)) {
        exit(EXIT_FAILURE);
    }
    memset(new_module_cumodule, 0, sizeof(SCCudaHlModuleCUmodule));

    /* select the ptx image based on the compute capability supported by all
     * devices (i.e. the lowest) */
    char* image = SCMalloc(strlen(ptx_image)+15);
    if (unlikely(image == NULL)) {
        exit(EXIT_FAILURE);
    }
    memset(image, 0x0, strlen(ptx_image)+15);

    int major = INT_MAX;
    int minor = INT_MAX;
    SCCudaDevices *devices = SCCudaGetDeviceList();
    int i=0;
    for (; i<devices->count; i++){
        if (devices->devices[i]->major_rev < major){
            major = devices->devices[i]->major_rev;
            minor = devices->devices[i]->minor_rev;
        }
        if (devices->devices[i]->major_rev == major &&
            devices->devices[i]->minor_rev < minor){
            minor = devices->devices[i]->minor_rev;
        }
    }
    snprintf(image, strlen(ptx_image) + 15, "%s_sm_%u%u",
             ptx_image, major, minor);

    /* we don't have a cuda module associated with this module.  Create a
     * cuda module, update the module with this cuda module reference and
     * then return the module refernce back to the calling function using
     * the argument */
    SCLogDebug("Loading kernel module: %s\n",image);
    if (SCCudaModuleLoadData(p_module, (void *)SCCudaPtxDumpGetModule(image)) == -1)
        goto error;
    SCFree(image);

    new_module_cumodule->cuda_module = p_module[0];
    new_module_cumodule->cuda_module_handle = SCCudaHlGetUniqueHandle();

    /* insert it into the cuda_modules list for the module instance */
    if (data->cuda_modules == NULL) {
        data->cuda_modules = new_module_cumodule;
        return new_module_cumodule->cuda_module_handle;
    }

    module_cumodules = data->cuda_modules;
    while (module_cumodules->next != NULL)
        module_cumodules = module_cumodules->next;
    module_cumodules->next = new_module_cumodule;

    return new_module_cumodule->cuda_module_handle;

 error:
    SCFree(image);
    return -1;
}