Exemplo n.º 1
0
static void
pocl_parse_event_filter ()
{
  const char *trace_filter;
  char *tmp_str, *save_ptr, *token;

  trace_filter = pocl_get_string_option ("POCL_TRACE_EVENT_FILTER", NULL);
  if (trace_filter == NULL)
    return;

  tmp_str = strdup (trace_filter);
  if (tmp_str == NULL)
    return;

  event_trace_filter = 0;
  while (1)
    {
      token = strtok_r (tmp_str, ",", &save_ptr);
      if (token == NULL)
        goto PARSE_OUT;
      if (strcmp (token, "queued") == 0)
        event_trace_filter |= (1 << CL_QUEUED);
      else if (strcmp (token, "submitted") == 0)
        event_trace_filter |= (1 << CL_SUBMITTED);
      else if (strcmp (token, "running") == 0)
        event_trace_filter |= (1 << CL_RUNNING);
      else if (strcmp (token, "complete") == 0)
        event_trace_filter |= (1 << CL_COMPLETE);

      tmp_str = NULL;
    }

PARSE_OUT:
  free (tmp_str);
}
Exemplo n.º 2
0
void
pocl_event_tracing_init ()
{
  const char *trace_env;
  unsigned i;

  if (tracing_initialized)
    return;

  trace_env = pocl_get_string_option ("POCL_TRACE_EVENT", NULL);
  if (trace_env == NULL)
    goto EVENT_INIT_OUT;

  /* Check if a tracer has a name matching the supplied one */
  for (i = 0; i < POCL_TRACER_COUNT; i++)
    {
      if (strcmp (trace_env, pocl_event_tracers[i]->name) == 0)
       {
         event_tracer = pocl_event_tracers[i];
         break;
       }
    }
  if (event_tracer == NULL)
    goto EVENT_INIT_OUT;

  pocl_parse_event_filter ();

  event_tracer->init ();

EVENT_INIT_OUT:
  tracing_initialized = 1;
}
Exemplo n.º 3
0
void pocl_cache_init_topdir() {

    if (cache_topdir_initialized)
        return;

    const char *tmp_path = pocl_get_string_option("POCL_CACHE_DIR", NULL);
    int needed;

    if (tmp_path && (pocl_exists(tmp_path))) {
        needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH, "%s", tmp_path);
    } else     {
#ifdef POCL_ANDROID
        char* process_name = pocl_get_process_name();
        needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH,
                          "/data/data/%s/cache/", process_name);
        free(process_name);

        if (!pocl_exists(cache_topdir))
            needed = snprintf(cache_topdir,
                              POCL_FILENAME_LENGTH,
                              "/sdcard/pocl/kcache");
#elif defined(_MSC_VER) || defined(__MINGW32__)
        tmp_path = getenv("LOCALAPPDATA");
        if (!tmp_path)
            tmp_path = getenv("TEMP");
        assert(tmp_path);
        needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH,
                          "%s\\pocl", tmp_path);
#else
        // "If $XDG_CACHE_HOME is either not set or empty, a default equal to
        // $HOME/.cache should be used."
        // http://standards.freedesktop.org/basedir-spec/latest/
        tmp_path = getenv("XDG_CACHE_HOME");

        if (tmp_path && tmp_path[0] != '\0') {
            needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH,
                              "%s/pocl/kcache", tmp_path);
        }
        else if ((tmp_path = getenv("HOME")) != NULL) {
            needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH,
                              "%s/.cache/pocl/kcache", tmp_path);
        }
        else {
            needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH,
                              "/tmp/pocl/kcache");
        }
#endif
    }

    if (needed >= POCL_FILENAME_LENGTH) {
        POCL_ABORT("pocl: cache path longer than maximum filename length");
    }

    assert(strlen(cache_topdir) > 0);
    if (pocl_mkdir_p(cache_topdir))
        POCL_ABORT("Could not create topdir for cache");
    cache_topdir_initialized = 1;

}
Exemplo n.º 4
0
static void
text_tracer_init ()
{
  const char *text_tracer_output;

  text_tracer_output = pocl_get_string_option ("POCL_TRACE_EVENT_OPT",
                                          "pocl_trace_events.log");
  text_tracer_file = fopen (text_tracer_output, "w");
  if (!text_tracer_file)
    POCL_ABORT ("Failed to open text tracer output\n");
}
Exemplo n.º 5
0
static inline void
build_program_compute_hash(cl_program program)
{
  SHA1_CTX hash_ctx;
  int total_binary_size, i;

  pocl_SHA1_Init(&hash_ctx);

  if (program->source)
    {
      pocl_SHA1_Update(&hash_ctx, (uint8_t*) program->source, strlen(program->source));
    }
  else  /* Program was created with clCreateProgramWithBinary() */
    {
      total_binary_size = 0;
      for (i = 0; i < program->num_devices; ++i)
        total_binary_size += program->binary_sizes[i];

      /* Binaries are stored in continuous chunk of memory starting from binaries[0] */
      pocl_SHA1_Update(&hash_ctx, (uint8_t*) program->binaries[0], total_binary_size);
    }

  if (program->compiler_options)
    pocl_SHA1_Update(&hash_ctx, (uint8_t*) program->compiler_options, 
                     strlen(program->compiler_options));

  /* The kernel compiler work-group function method affects the
     produced binary heavily. */
  const char *wg_method = 
    pocl_get_string_option ("POCL_WORK_GROUP_METHOD", "");

  pocl_SHA1_Update (&hash_ctx, (uint8_t*) wg_method, strlen (wg_method));
  pocl_SHA1_Update (&hash_ctx, (uint8_t*) PACKAGE_VERSION, 
                    strlen (PACKAGE_VERSION));
  pocl_SHA1_Update (&hash_ctx, (uint8_t*) LLVM_VERSION, 
                    strlen (LLVM_VERSION));
  pocl_SHA1_Update (&hash_ctx, (uint8_t*) POCL_BUILD_TIMESTAMP, 
                    strlen (POCL_BUILD_TIMESTAMP));
  /*devices may include their own information to hash */
  for (i = 0; i < program->num_devices; ++i)
    {
      if (program->devices[i]->ops->build_hash)
        program->devices[i]->ops->build_hash (program->devices[i]->data, 
                                              &hash_ctx);
    }
  
  pocl_SHA1_Final(&hash_ctx, program->build_hash);
}
Exemplo n.º 6
0
cl_int
compile_and_link_program(int compile_program,
                         int link_program,
                         cl_program program,
                         cl_uint num_devices,
                         const cl_device_id *device_list,
                         const char *options,
                         cl_uint num_input_headers,
                         const cl_program *input_headers,
                         const char **header_include_names,
                         cl_uint num_input_programs,
                         const cl_program *input_programs,
                         void (CL_CALLBACK *pfn_notify) (cl_program program,
                                                         void *user_data),
                         void *user_data)
{
  char program_bc_path[POCL_FILENAME_LENGTH];
  char link_options[512];
  int errcode, error;
  int create_library = 0;
  int requires_cr_sqrt_div = 0;
  int spir_build = 0;
  unsigned flush_denorms = 0;
  uint64_t fsize;
  cl_device_id *unique_devlist = NULL;
  char *binary = NULL;
  unsigned device_i = 0, actually_built = 0;
  size_t i, j;
  char *temp_options = NULL;
  const char *extra_build_options =
    pocl_get_string_option ("POCL_EXTRA_BUILD_FLAGS", NULL);
  int build_error_code
      = (link_program ? CL_BUILD_PROGRAM_FAILURE : CL_COMPILE_PROGRAM_FAILURE);

  POCL_GOTO_LABEL_COND (PFN_NOTIFY, (program == NULL), CL_INVALID_PROGRAM);

  POCL_GOTO_LABEL_COND (PFN_NOTIFY, (num_devices > 0 && device_list == NULL),
                        CL_INVALID_VALUE);
  POCL_GOTO_LABEL_COND (PFN_NOTIFY, (num_devices == 0 && device_list != NULL),
                        CL_INVALID_VALUE);

  POCL_GOTO_LABEL_COND (PFN_NOTIFY, (pfn_notify == NULL && user_data != NULL),
                        CL_INVALID_VALUE);

  POCL_GOTO_LABEL_ON (PFN_NOTIFY, program->kernels, CL_INVALID_OPERATION,
                      "Program already has kernels\n");

  POCL_GOTO_LABEL_ON (PFN_NOTIFY,
                      (program->source == NULL && program->binaries == NULL),
                      CL_INVALID_PROGRAM,
                      "Program doesn't have sources or binaries! You need "
                      "to call clCreateProgramWith{Binary|Source} first\n");

  POCL_GOTO_LABEL_ON (PFN_NOTIFY,
                      ((program->source == NULL) && (link_program == 0)),
                      CL_INVALID_OPERATION,
                      "Cannot clCompileProgram when program has no source\n");

  POCL_LOCK_OBJ (program);

  program->main_build_log[0] = 0;

  /* TODO this should be somehow utilized at linking */
  POCL_MEM_FREE (program->compiler_options);

  if (extra_build_options)
    {
      size_t len = (options != NULL) ? strlen (options) : 0;
      len += strlen (extra_build_options) + 2;
      temp_options = (char *)malloc (len);

      temp_options[0] = 0;
      if (options != NULL)
        {
          strcpy (temp_options, options);
          strcat (temp_options, " ");
        }
      strcat (temp_options, extra_build_options);
    }
  else
    temp_options = (char*) options;

  if (temp_options)
    {
      i = strlen (temp_options);
      size_t size = i + 512; /* add some space for pocl-added options */
      program->compiler_options = (char *)malloc (size);
      errcode = process_options (temp_options, program->compiler_options,
                                 link_options, program, compile_program,
                                 link_program, &create_library, &flush_denorms,
                                 &requires_cr_sqrt_div, &spir_build, size);
      if (errcode != CL_SUCCESS)
        goto ERROR_CLEAN_OPTIONS;
    }

  POCL_MSG_PRINT_LLVM ("building program with options %s\n",
                       program->compiler_options);


  program->flush_denorms = flush_denorms;
#if !(defined(__x86_64__) && defined(__GNUC__))
  if (flush_denorms)
    {
      POCL_MSG_WARN ("flush to zero is currently only implemented for "
                     "x86-64 & gcc/clang, ignoring flag\n");
    }
#endif

  /* DEVICE LIST */
  if (num_devices == 0)
    {
      num_devices = program->num_devices;
      device_list = program->devices;
    }
  else
    {
      // convert subdevices to devices and remove duplicates
      cl_uint real_num_devices = 0;
      unique_devlist = pocl_unique_device_list (device_list, num_devices,
                                                &real_num_devices);
      num_devices = real_num_devices;
      device_list = unique_devlist;
    }

  clean_program_on_rebuild (program);

  /* Build the fully linked non-parallel bitcode for all
         devices. */
  for (device_i = 0; device_i < program->num_devices; ++device_i)
    {
      cl_device_id device = program->devices[device_i];

      /* find the device in the supplied devices-to-build-for list */
      int found = 0;
      for (i = 0; i < num_devices; ++i)
          if (device_list[i] == device) found = 1;
      if (!found) continue;

      if (requires_cr_sqrt_div
          && !(device->single_fp_config & CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT))
        {
          APPEND_TO_MAIN_BUILD_LOG (REQUIRES_CR_SQRT_DIV_ERR);
          POCL_GOTO_ERROR_ON (1, build_error_code,
                              REQUIRES_CR_SQRT_DIV_ERR " %s\n",
                              device->short_name);
        }
      actually_built++;

      /* clCreateProgramWithSource */
      if (program->source)
        {
#ifdef OCS_AVAILABLE
          if (device->compiler_available == CL_TRUE)
            {
              POCL_MSG_PRINT_INFO ("building from sources for device %d\n",
                                   device_i);
              error = pocl_llvm_build_program (
                  program, device_i, program->compiler_options,
                  program_bc_path, num_input_headers, input_headers,
                  header_include_names, (create_library ? 0 : link_program));
              POCL_GOTO_ERROR_ON ((error != 0), build_error_code,
                                  "pocl_llvm_build_program() failed\n");
            }
          else
#endif
            {
              APPEND_TO_MAIN_BUILD_LOG (
                  "Cannot build a program from sources with pocl "
                  "that does not have online compiler support\n");
              POCL_GOTO_ERROR_ON (1, CL_COMPILER_NOT_AVAILABLE, "%s",
                                  program->main_build_log);
            }
        }
      /* clCreateProgramWithBinaries */
      else if (program->binaries[device_i]
               && (program->pocl_binaries[device_i] == NULL))
        {
#ifdef OCS_AVAILABLE
          /* bitcode is now either plain LLVM IR or SPIR IR */
          int spir_binary = bitcode_is_spir ((char*)program->binaries[device_i],
                                             program->binary_sizes[device_i]);
          if (spir_binary)
            POCL_MSG_PRINT_LLVM ("LLVM-SPIR binary detected\n");
          else
            POCL_MSG_PRINT_LLVM ("building from a BC binary for device %d\n",
                                 device_i);

          if (spir_binary)
            {
#ifdef ENABLE_SPIR
              if (!strstr (device->extensions, "cl_khr_spir"))
                {
                  APPEND_TO_MAIN_BUILD_LOG (REQUIRES_SPIR_SUPPORT);
                  POCL_GOTO_ERROR_ON (1, build_error_code,
                                      REQUIRES_SPIR_SUPPORT " %s\n",
                                      device->short_name);
                }
              if (!spir_build)
                POCL_MSG_WARN (
                    "SPIR binary provided, but no spir in build options\n");
              /* SPIR binaries need to be explicitly linked to the kernel
               * library. for non-SPIR binaries this happens as part of build
               * process when program.bc is generated. */
              error
                  = pocl_llvm_link_program (program, device_i, program_bc_path,
                                            0, NULL, NULL, NULL, 0, 1);

              POCL_GOTO_ERROR_ON (error, CL_LINK_PROGRAM_FAILURE,
                                  "Failed to link SPIR program.bc\n");
#else
              APPEND_TO_MAIN_BUILD_LOG (REQUIRES_SPIR_SUPPORT);
              POCL_GOTO_ERROR_ON (1, build_error_code,
                                  REQUIRES_SPIR_SUPPORT " %s\n",
                                  device->short_name);
#endif
            }

#else
          APPEND_TO_MAIN_BUILD_LOG (
              "Cannot build program from LLVM IR binaries with "
              "pocl that does not have online compiler support\n");
          POCL_GOTO_ERROR_ON (1, CL_COMPILER_NOT_AVAILABLE, "%s",
                              program->main_build_log);
#endif
        }
      else if (program->pocl_binaries[device_i])
        {
          POCL_MSG_PRINT_INFO("having a poclbinary for device %d\n", device_i);
#ifdef OCS_AVAILABLE
          if (program->binaries[device_i] == NULL)
            {
              POCL_MSG_WARN (
                  "pocl-binary for this device doesn't contain "
                  "program.bc - you won't be able to rebuild/link it\n");
              /* do not try to read program.bc or LLVM IRs
               * TODO maybe read LLVM IRs ?*/
              continue;
            }
#else
          continue;
#endif
        }
      else if (link_program && (num_input_programs > 0))
        {
#ifdef OCS_AVAILABLE
          /* just link binaries. */
          unsigned char *cur_device_binaries[num_input_programs];
          size_t cur_device_binary_sizes[num_input_programs];
          void *cur_llvm_irs[num_input_programs];
          for (j = 0; j < num_input_programs; j++)
            {
              assert (device == input_programs[j]->devices[device_i]);
              cur_device_binaries[j] = input_programs[j]->binaries[device_i];

              assert (cur_device_binaries[j]);
              cur_device_binary_sizes[j]
                  = input_programs[j]->binary_sizes[device_i];

              if (input_programs[j]->llvm_irs[device_i] == NULL)
                pocl_update_program_llvm_irs (input_programs[j], device_i);

              cur_llvm_irs[j] = input_programs[j]->llvm_irs[device_i];
              assert (cur_llvm_irs[j]);
            }
          error = pocl_llvm_link_program (
              program, device_i, program_bc_path, num_input_programs,
              cur_device_binaries, cur_device_binary_sizes, cur_llvm_irs,
              create_library, 0);
          POCL_GOTO_ERROR_ON ((error != CL_SUCCESS), CL_LINK_PROGRAM_FAILURE,
                              "pocl_llvm_link_program() failed\n");
#else
          POCL_GOTO_ERROR_ON ((1), CL_LINK_PROGRAM_FAILURE,
                              "clCompileProgram/clLinkProgram/clBuildProgram"
                              " require a pocl built with LLVM\n");

#endif
        }
      else
        {
          POCL_GOTO_ERROR_ON (1, CL_INVALID_BINARY,
                              "No sources nor binaries for device %s - can't "
                              "build the program\n", device->short_name);
        }

#ifdef OCS_AVAILABLE
      /* Read binaries from program.bc to memory */
      if (program->binaries[device_i] == NULL)
        {
          errcode = pocl_read_file(program_bc_path, &binary, &fsize);
          POCL_GOTO_ERROR_ON(errcode, CL_BUILD_ERROR,
                             "Failed to read binaries from program.bc to "
                             "memory: %s\n", program_bc_path);

          program->binary_sizes[device_i] = (size_t)fsize;
          program->binaries[device_i] = (unsigned char *)binary;
        }

      if (program->llvm_irs[device_i] == NULL)
        {
          pocl_update_program_llvm_irs(program, device_i);
        }
      /* Maintain a 'last_accessed' file in every program's
       * cache directory. Will be useful for cache pruning script
       * that flushes old directories based on LRU */
      pocl_cache_update_program_last_access(program, device_i);
#endif

    }

  POCL_GOTO_ERROR_ON ((actually_built < num_devices), build_error_code,
                      "Some of the devices on the argument-supplied list are"
                      "not available for the program, or do not exist\n");

  program->build_status = CL_BUILD_SUCCESS;
  program->binary_type = CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
  /* if program will be compiled using clCompileProgram its binary_type
   * will be set to CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT.
   *
   * if program was created by clLinkProgram which is called
   * with the –createlibrary link option its binary_type will be set to
   * CL_PROGRAM_BINARY_TYPE_LIBRARY.
   */
  if (create_library)
    program->binary_type = CL_PROGRAM_BINARY_TYPE_LIBRARY;
  if (compile_program && !link_program)
    program->binary_type = CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;

  assert(program->num_kernels == 0);

  /* get non-device-specific kernel metadata. We can stop after finding
   * the first method that works.*/
  for (device_i = 0; device_i < program->num_devices; device_i++)
    {
#ifdef OCS_AVAILABLE
      if (program->binaries[device_i])
        {
          program->num_kernels
              = pocl_llvm_get_kernel_count (program, device_i);
          if (program->num_kernels)
            {
              program->kernel_meta = calloc (program->num_kernels,
                                             sizeof (pocl_kernel_metadata_t));
              pocl_llvm_get_kernels_metadata (program, device_i);
            }
          break;
        }
#endif
      if (program->pocl_binaries[device_i])
        {
          program->num_kernels
              = pocl_binary_get_kernel_count (program, device_i);
          if (program->num_kernels)
            {
              program->kernel_meta = calloc (program->num_kernels,
                                             sizeof (pocl_kernel_metadata_t));
              pocl_binary_get_kernels_metadata (program, device_i);
            }
          break;
        }
    }

  POCL_GOTO_ERROR_ON ((device_i >= program->num_devices), CL_INVALID_BINARY,
                      "Could find kernel metadata in the built program\n");

  /* calculate device-specific kernel hashes. */
  for (j = 0; j < program->num_kernels; ++j)
    {
      program->kernel_meta[j].build_hash
          = calloc (program->num_devices, sizeof (pocl_kernel_hash_t));

      for (device_i = 0; device_i < program->num_devices; device_i++)
        {
          pocl_calculate_kernel_hash (program, j, device_i);
        }
    }

  errcode = CL_SUCCESS;
  goto FINISH;

ERROR:
  free_meta (program);

  program->kernels = NULL;

  for (device_i = 0; device_i < program->num_devices; device_i++)
    {
      if (program->source)
        {
          POCL_MEM_FREE (program->binaries[device_i]);
          program->binary_sizes[device_i] = 0;
        }
    }

ERROR_CLEAN_OPTIONS:
  if (temp_options != options)
    free (temp_options);

  program->build_status = CL_BUILD_ERROR;

FINISH:
  POCL_UNLOCK_OBJ (program);
  POCL_MEM_FREE (unique_devlist);

PFN_NOTIFY:
  if (pfn_notify)
    pfn_notify (program, user_data);

  return errcode;
}
Exemplo n.º 7
0
void
pocl_cuda_init (cl_device_id device, const char *parameters)
{
  CUresult result;

  result = cuInit (0);
  CUDA_CHECK (result, "cuInit");

  if (device->data)
    return;

  pocl_cuda_device_data_t *data = malloc (sizeof (pocl_cuda_device_data_t));
  result = cuDeviceGet (&data->device, 0);
  CUDA_CHECK (result, "cuDeviceGet");

  // Get specific device name
  device->long_name = device->short_name = malloc (256 * sizeof (char));
  cuDeviceGetName (device->long_name, 256, data->device);

  // Get other device properties
  cuDeviceGetAttribute ((int *)&device->max_work_group_size,
                        CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK,
                        data->device);
  cuDeviceGetAttribute ((int *)(device->max_work_item_sizes + 0),
                        CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_X, data->device);
  cuDeviceGetAttribute ((int *)(device->max_work_item_sizes + 1),
                        CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_Y, data->device);
  cuDeviceGetAttribute ((int *)(device->max_work_item_sizes + 2),
                        CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_Z, data->device);
  cuDeviceGetAttribute (
      (int *)&device->local_mem_size,
      CU_DEVICE_ATTRIBUTE_MAX_SHARED_MEMORY_PER_MULTIPROCESSOR, data->device);
  cuDeviceGetAttribute ((int *)&device->max_compute_units,
                        CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT,
                        data->device);
  cuDeviceGetAttribute ((int *)&device->max_clock_frequency,
                        CU_DEVICE_ATTRIBUTE_CLOCK_RATE, data->device);
  cuDeviceGetAttribute ((int *)&device->error_correction_support,
                        CU_DEVICE_ATTRIBUTE_ECC_ENABLED, data->device);
  cuDeviceGetAttribute ((int *)&device->host_unified_memory,
                        CU_DEVICE_ATTRIBUTE_INTEGRATED, data->device);
  cuDeviceGetAttribute ((int *)&device->max_constant_buffer_size,
                        CU_DEVICE_ATTRIBUTE_TOTAL_CONSTANT_MEMORY,
                        data->device);

  device->preferred_vector_width_char = 1;
  device->preferred_vector_width_short = 1;
  device->preferred_vector_width_int = 1;
  device->preferred_vector_width_long = 1;
  device->preferred_vector_width_float = 1;
  device->preferred_vector_width_double = 1;
  device->preferred_vector_width_half = 0;
  device->native_vector_width_char = 1;
  device->native_vector_width_short = 1;
  device->native_vector_width_int = 1;
  device->native_vector_width_long = 1;
  device->native_vector_width_float = 1;
  device->native_vector_width_double = 1;
  device->native_vector_width_half = 0;

  device->single_fp_config = CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO
                             | CL_FP_ROUND_TO_INF | CL_FP_FMA | CL_FP_INF_NAN
                             | CL_FP_DENORM;
  device->double_fp_config = CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO
                             | CL_FP_ROUND_TO_INF | CL_FP_FMA | CL_FP_INF_NAN
                             | CL_FP_DENORM;

  device->local_mem_type = CL_LOCAL;
  device->host_unified_memory = 0;

  // Get GPU architecture name
  int sm_maj, sm_min;
  cuDeviceGetAttribute (&sm_maj, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR,
                        data->device);
  cuDeviceGetAttribute (&sm_min, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR,
                        data->device);
  char *gpu_arch = malloc (16 * sizeof (char));
  snprintf (gpu_arch, 16, "sm_%d%d", sm_maj, sm_min);
  device->llvm_cpu = pocl_get_string_option ("POCL_CUDA_GPU_ARCH", gpu_arch);
  POCL_MSG_PRINT_INFO ("[CUDA] GPU architecture = %s\n", device->llvm_cpu);

  // Create context
  result = cuCtxCreate (&data->context, CU_CTX_MAP_HOST, data->device);
  CUDA_CHECK (result, "cuCtxCreate");

  // Get global memory size
  size_t memfree, memtotal;
  result = cuMemGetInfo (&memfree, &memtotal);
  device->max_mem_alloc_size = max (memtotal / 4, 128 * 1024 * 1024);
  device->global_mem_size = memtotal;

  device->data = data;
}
Exemplo n.º 8
0
/**
 * Generate code from the final bitcode using the LLVM
 * tools.
 *
 * Uses an existing (cached) one, if available.
 *
 * @param tmpdir The directory of the work-group function bitcode.
 * @param return the generated binary filename.
 */
const char*
llvm_codegen (const char* tmpdir, cl_kernel kernel, cl_device_id device) {

  const char* pocl_verbose_ptr = 
    pocl_get_string_option("POCL_VERBOSE", (char*)NULL);
  int pocl_verbose = pocl_verbose_ptr && *pocl_verbose_ptr;

  char command[COMMAND_LENGTH];
  char bytecode[POCL_FILENAME_LENGTH];
  char objfile[POCL_FILENAME_LENGTH];

  char* module = (char*) malloc(min(POCL_FILENAME_LENGTH, 
	   strlen(tmpdir) + strlen(kernel->function_name) + 5)); // strlen of / .so 4+1

  int error;
  cl_program program = kernel->program;

  error = snprintf 
    (module, POCL_FILENAME_LENGTH,
     "%s/%s.so", tmpdir, kernel->function_name);

  assert (error >= 0);

  error = snprintf
    (objfile, POCL_FILENAME_LENGTH,
     "%s/%s.so.o", tmpdir, kernel->function_name);
  assert (error >= 0);


  if (access (module, F_OK) != 0)
    {
      error = snprintf (bytecode, POCL_FILENAME_LENGTH,
                        "%s/%s", tmpdir, POCL_PARALLEL_BC_FILENAME);
      assert (error >= 0);
      
      error = pocl_llvm_codegen( kernel, device, bytecode, objfile);
      assert (error == 0);

      // clang is used as the linker driver in LINK_CMD
      error = snprintf (command, COMMAND_LENGTH,
#ifndef ANDROID
            LINK_CMD " " HOST_CLANG_FLAGS " " HOST_LD_FLAGS " -o %s %s",
#else
            ANDROID_POCL_PREFIX"/bin/ld " HOST_LD_FLAGS " -o %s %s "
            " /system/lib/crtend_so.o /system/lib/crtbegin_so.o -ldl -lc ",
#endif
            module, objfile);
      assert (error >= 0);

      if (pocl_verbose) {
        fprintf(stderr, "[pocl] executing [%s]\n", command);
        fflush(stderr);
      }
      error = system (command);
      assert (error == 0);

      /* Save space in kernel cache */
      if (!pocl_get_bool_option("POCL_LEAVE_KERNEL_COMPILER_TEMP_FILES", 0))
        {
          pocl_remove_file(objfile);
          pocl_remove_file(bytecode);
        }
    }
  return module;
}
Exemplo n.º 9
0
static inline void
build_program_compute_hash(cl_program program,
                           unsigned   device_i,
                           const char*      preprocessed_source,
                           size_t     source_len)
{
    SHA1_CTX hash_ctx;
    unsigned i;
    cl_device_id device = program->devices[device_i];

    pocl_SHA1_Init(&hash_ctx);

    if (program->source) {
        assert(preprocessed_source);
        assert(source_len > 0);
        pocl_SHA1_Update(&hash_ctx, (uint8_t*)preprocessed_source,
                         source_len);
    } else     { /* Program was created with clCreateProgramWithBinary() */
        assert(program->binaries[device_i]);
        pocl_SHA1_Update(&hash_ctx,
                         (uint8_t*) program->binaries[device_i],
                         program->binary_sizes[device_i]);
    }

    if (program->compiler_options)
        pocl_SHA1_Update(&hash_ctx, (uint8_t*) program->compiler_options,
                         strlen(program->compiler_options));

    /* The kernel compiler work-group function method affects the
       produced binary heavily. */
    const char *wg_method=
        pocl_get_string_option("POCL_WORK_GROUP_METHOD", "");

    pocl_SHA1_Update(&hash_ctx, (uint8_t*) wg_method, strlen(wg_method));
    pocl_SHA1_Update(&hash_ctx, (uint8_t*) PACKAGE_VERSION,
                     strlen(PACKAGE_VERSION));
    pocl_SHA1_Update(&hash_ctx, (uint8_t*) LLVM_VERSION,
                     strlen(LLVM_VERSION));
    pocl_SHA1_Update(&hash_ctx, (uint8_t*) POCL_BUILD_TIMESTAMP,
                     strlen(POCL_BUILD_TIMESTAMP));
    pocl_SHA1_Update(&hash_ctx, (const uint8_t *)POCL_KERNELLIB_SHA1,
                     strlen(POCL_KERNELLIB_SHA1));
    /*devices may include their own information to hash */
    if (device->ops->build_hash)
        device->ops->build_hash(device->data, &hash_ctx);


    uint8_t digest[SHA1_DIGEST_SIZE];
    pocl_SHA1_Final(&hash_ctx, digest);

    unsigned char* hashstr = program->build_hash[device_i];
    for (i=0; i < SHA1_DIGEST_SIZE; i++)
        {
            *hashstr++ = (digest[i] & 0x0F) + 65;
            *hashstr++ = ((digest[i] & 0xF0) >> 4) + 65;
        }
    *hashstr = 0;

    program->build_hash[device_i][2] = '/';

}