Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] View of /branches/vis12-cl/src/compiler/cl-target/fragments/c-init.in
ViewVC logotype

View of /branches/vis12-cl/src/compiler/cl-target/fragments/c-init.in

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2743 - (download) (annotate)
Sun Sep 28 02:54:54 2014 UTC (5 years, 1 month ago) by jhr
File size: 6648 byte(s)
  Working on OpenCL support
#ifdef USE_CALLBACK
/*! callback to log OpenCL error messages */
static void LogMessages (const char *errstr, const void *pvtInfo, size_t cb, void *userData)
{
    @PREFIX@World_t *wrld = (@PREFIX@World_t *)userData;
    biffMsgAddf (
	wrld->errors,
	"***** error log *****\n"	\
	"%s\n"				\
	"***** end error log *****\n", errstr); 
}
#endif

/*! initialize the OpenCL execution context, including loading and compiling the OpenCL
 *    program.
 *  \param wrld the Diderot execution information.
 *  \return true if there is an error, otherwise false.
 */
static bool InitCL (@PREFIX@World_t *wrld, int devID)
{
    cl_int              sts;
    int                 pltIx = 0;  // main patform index
    Diderot_DeviceInfo_t *dev = 0;
    Diderot_OCLInfo_t	*oclInfo = wrld->oclInfo;

    if ((0 <= devID) && (devID < oclInfo->platforms[pltIx].numDevices)) {
      // use the user supplied device
        if (Diderot_isGPUDevice (&(oclInfo->platforms[pltIx].devices[devID]))
        &&  oclInfo->platforms[pltIx].devices[devID].isAvail) {
            dev = &(oclInfo->platforms[pltIx].devices[devID]);
        }
        else {
            biffMsgAddf (wrld->errors,
		"specified OpenCL device %d is not a GPU or is not available\n", devID);
            return true;
        }
    }
    else {
      // find a GPU on platform[0]
        for (int i = 0;  i < oclInfo->platforms[pltIx].numDevices;  i++) {
            if (Diderot_isGPUDevice (&(oclInfo->platforms[pltIx].devices[i]))
            &&  oclInfo->platforms[pltIx].devices[i].isAvail) {
                devID = i;
                dev = &(oclInfo->platforms[pltIx].devices[i]);
                break;
            }
        }
        if (dev == 0) {
            biffMsgAddf (wrld->errors, "unable to find GPU device\n");
            return true;
        }
    }

    if (wrld->verboseFlg) {
        fprintf (stderr, "using platform %d, device %d: %s\n",
            pltIx, devID, dev->name);
    }

  // create the context; we pass the world as user data so that we can record errors
  // in the errors biff
#ifdef USE_CALLBACK
    cl_context cxt = clCreateContext(0, 1, &(dev->id), LogMessages, wrld, &sts);
#else
    cl_context cxt = clCreateContext(0, 1, &(dev->id), 0, 0, &sts);
#endif
    if (sts != CL_SUCCESS) {
        biffMsgAddf (wrld->errors, "error creating OpenCL context\n");
        return true;
    }

  // create the program from the source
    int fnameLen = strlen(wrld->name) + 4;  // name + ".cl\0"
    char *fname = (char *)CheckedAlloc(fnameLen);
    snprintf(fname, fnameLen, "%s.cl", wrld->name);
    cl_program prog = Diderot_LoadProgramFromSource ((WorldPrefix_t *)wrld, cxt, fname, &sts);
    free (fname);
    if (sts != CL_SUCCESS) {
        biffMsgAddf (wrld->errors, "error creating program\n");
        return true;
    }

  // build the program
    char options[1024];
    snprintf (options, sizeof(options),
        "-D DIDEROT_CL_VERSION=%d -D DIDEROT_CU_WIDTH=%d -I %s -w",
        100*dev->majorVersion + dev->minorVersion,
        dev->cuWidth,
        DIDEROT_INCLUDE_PATH);
    if (wrld->verboseFlg) {
        fprintf (stderr, "clBuildProgram options: %s\n", options);
    }
    sts = clBuildProgram (prog, 1, &(dev->id), options, 0, 0);
    if (sts != CL_SUCCESS) {
      /* this is a likely a bug in the Diderot compiler, which has produced incorrect OpenCL
       * code, so we report the error directly to stderr.
       */
        size_t logSzb;
        clGetProgramBuildInfo (prog, dev->id, CL_PROGRAM_BUILD_LOG, 0, 0, &logSzb);
        char *log = CheckedAlloc(logSzb+1);
        clGetProgramBuildInfo (prog, dev->id, CL_PROGRAM_BUILD_LOG, logSzb, log, &logSzb);
        log[logSzb] = '\0';
/*
        biffMsgAddf (wrld->errors, "error compiling program:\n%s\n", log);
*/
        fprintf (stderr, "error compiling program:\n%s\n", log);
        free (log);
        return true;
    }

  // create the command queue
    cl_command_queue q = clCreateCommandQueue(cxt, dev->id, 0, &sts);
    if (sts != CL_SUCCESS) {
        biffMsgAddf (wrld->errors, "error creating OpenCL command queue\n");
        return true;
    }

  // initialize world info
    wrld->device = dev;
    wrld->context = cxt;
    wrld->cmdQ = q;
    wrld->prog = prog;

  // bind kernels
    if (BindKernels (wrld)) {
        biffMsgAddf (wrld->errors, "error binding kernels\n");
        return true;
    }

    return false;
}

// Allocate the program's world
//
@PREFIX@World_t *@PREFIX@New ()
{
    @PREFIX@World_t *wrld = NEW(@PREFIX@World_t);
    if (wrld == 0)
	return 0;

    wrld->name		= ProgramName;
    wrld->errors	= biffMsgNew("DIDEROT");

    if (wrld->errors == 0) {
        FREE (wrld);
	return 0;
    }

    wrld->stage         = POST_NEW;
    wrld->verboseFlg	= false;
    wrld->nStrandTys	= 1;  /* FIXME */
/*
    wrld->strandDesc	= &Strand_@STRAND@;
*/

  // get information about OpenCL support
    wrld->oclInfo = Diderot_GetCLInfo((WorldPrefix_t *)wrld);
    if (wrld->oclInfo == 0) {
        return 0;
    }

    wrld->gpuDevId	= -1;

    return wrld;

}

//! Initialize the program's world; returns true on error.
//
bool @PREFIX@Init (@PREFIX@World_t *wrld)
{
    if (wrld->stage != POST_NEW) {
	biffMsgAdd (wrld->errors, "multiple calls to @PREFIX@Init");
	return true;
    }

  // initialize the OpenCL context, etc.
    if (InitCL(wrld, wrld->gpuDevId)) {
        return true;
    }

    cl_int sts;

  // get the sizes of GPU-side data structures
    cl_mem clSizes = clCreateBuffer(wrld->context, CL_MEM_WRITE_ONLY, sizeof(@PREFIX@Sizes_t), 0, &sts);
    if (CheckOCLStatus(wrld, sts, "unable to allocate GPU memory"))
	return true;
    sts = clSetKernelArg(wrld->GetSizesKern, 0, sizeof(cl_mem), &clSizes);
    if (CheckOCLStatus(wrld, sts, "error setting arguments for sizes kernel"))
	return true;
    sts = clEnqueueTask(wrld->cmdQ, wrld->GetSizesKern, 0, NULL, NULL);
    if (CheckOCLStatus(wrld, sts, "error enqueuing sizes kernel"))
	return true;
    sts = clEnqueueReadBuffer(wrld->cmdQ, clSizes, CL_TRUE, 0, sizeof(@PREFIX@Sizes_t), &(wrld->oclSizes), 0, 0, 0);
    if (CheckOCLStatus(wrld, sts, "error getting sizes"))
	return true;

  // allocate memory for the device-side globals structure
    wrld->globalsBuf = clCreateBuffer (wrld->context, CL_MEM_READ_WRITE, wrld->oclSizes.globSzB, 0, &sts);
    if (CheckOCLStatus(wrld, sts, "error creating OpenCL globals memory buffer"))
	return true;

/* FIXME: need to allocate scheduler data structures */

#ifndef DIDEROT_STANDALONE_EXEC
  // initialize the defined flags for the input globals
    @PREFIX@InitDefined (wrld);
#endif

    wrld->stage = POST_INIT;

    return false;

}

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0