コード例 #1
0
/* __ompc_remove_task_from_pool_simple_2level:
 * Takes a task from the task pool. First tries to get a task from the current
 * thread's task queue. If that doesn't work, then it will look for work in
 * the community queue. If that's also empty, then it will attempt to steal a
 * task from another task queue (so long as there are no other tasks, not in a
 * barrier, that are tied to the current thread).
 *
 * Note: The restriction on stealing is overly conservative. Even if there are
 * tasks tied to the current thread and not in a barrier ([*]), we should be
 * able to steal any untied tasks, or tied tasks that descend from all tasks
 * in [*]. But this implementation does not separate untied tasks from tied
 * tasks, and also does not track descendants in the task pool.
 */
omp_task_t *__ompc_remove_task_from_pool_simple_2level(omp_task_pool_t *pool)
{
  omp_task_t *task, *current_task;
  omp_team_t *team;
  omp_v_thread_t *current_thread;
  omp_queue_t *my_queue;
  omp_queue_t *victim_queue;
  omp_task_queue_level_t *per_thread, *community;
  int myid = __omp_myid;

  Is_True(pool != NULL, ("__ompc_remove_task_from_pool: task pool is uninitialized"));

  current_task = __omp_current_task;
  current_thread = __omp_current_v_thread;
  per_thread = &pool->level[PER_THREAD];
  community = &pool->level[COMMUNITY];

  task = __ompc_task_queue_get(&per_thread->task_queue[myid]);

  /* if no task in local queue, we will look in another queue so long as there
   * are no suspended tasks tied to thread and the current task is either in a
   * barrier or its not tied
   */
  if (task == NULL && !current_thread->num_suspended_tied_tasks &&
      (__ompc_task_state_is_in_barrier(current_task) ||
       !__ompc_task_is_tied(current_task))) {

    if (__omp_task_chunk_size > 1) {
      /* this will steal a chunk of tasks, instead of just 1, from the
       * community
       * queue */
      task = __ompc_task_queue_steal_chunk(community->task_queue,
          &per_thread->task_queue[myid],
          __omp_task_chunk_size);
    } else {
      task = __ompc_task_queue_steal(community->task_queue);
    }

    if (task == NULL) {
      int first_victim, victim = 0;
      int team_size = pool->team_size;
      victim = (rand_r(&__omp_seed) % (team_size - 1));
      if (victim >= myid) victim++;
      /* cycle through to find a queue with work to steal */
      first_victim = victim;
      while (1) {
        while (__ompc_queue_is_empty(&per_thread->task_queue[victim])) {
          victim++;
          if (victim == myid)
            victim++;
          if (victim == team_size)
            victim = 0;
          if (victim == first_victim)
            return NULL;
        }
        task = __ompc_task_queue_steal(&per_thread->task_queue[victim]);
        if ( task != NULL ) return task;
      }
    }
  }

  return task;
}
コード例 #2
0
/* __ompc_remove_task_from_pool_default:
 *Takes task from the task pool.
 *
 * Takes a task from the task pool. First tries to get a task from the current
 * thread's task queue. If that doesn't work, then it will attempt to steal a
 * task from another task queue (so long as there are no other tasks, not in a
 * barrier, that are tied to the current thread).
 */
omp_task_t *__ompc_remove_task_from_pool_default(omp_task_pool_t *pool)
{
  omp_task_t *task, *current_task;
  omp_team_t *team;
  omp_v_thread_t *current_thread;
  omp_queue_t *my_queue;
  omp_queue_t *victim_queue;
  omp_task_queue_level_t *per_thread;
  int myid = __omp_myid;

  Is_True(pool != NULL, ("__ompc_remove_task_from_pool: task pool is uninitialized"));

  current_task = __omp_current_task;
  current_thread = __omp_current_v_thread;
  per_thread = &pool->level[PER_THREAD];

  /* We get only from the tail for tied tasks. This is necessary to guarantee
   * that tied tasks are only scheduled if they are descendants of every
   * suspended tied task not at a barrier */
  task = __ompc_queue_get_tail(&per_thread->task_queue[TIED_IDX(myid)]);

  /* for untied tasks, we can get from the head or tail, depending on what
   * O64_OMP_TASK_QUEUE is set to */
  if (task == NULL)
    task = __ompc_task_queue_get(&per_thread->task_queue[UNTIED_IDX(myid)]);


  /* check if there are any untied tasks available in the other task queues */
  if (task == NULL) {
    int first_victim, victim = 0;
    int team_size = pool->team_size;

    if (team_size < 2)
      return NULL;

    victim = (rand_r(&__omp_seed) % (team_size - 1));
    if (victim >= myid) victim++;
    /* cycle through to find a queue with work to steal */
    first_victim = victim;
    while (1) {
      while (__ompc_queue_lockless_is_empty(
                     &per_thread->task_queue[UNTIED_IDX(victim)])) {
        victim++;
        if (victim == myid)
          victim++;
        if (victim == team_size)
          victim = 0;
        if (victim == first_victim)
         goto CHECK_TIED_TASK_QUEUES;
      }
      task = __ompc_task_queue_steal(
                     &per_thread->task_queue[UNTIED_IDX(victim)]);
      if ( task != NULL ) {
        /*
        if (!__ompc_task_state_is_unscheduled(task)) {
          // Is_True(0, ("state of task from queue was not unscheduled"));
          printf("\n... (1) skipping over a task with state %s; queue size is %d \n",
                  __ompc_task_get_state_string(task),
         __ompc_queue_num_used_slots(&per_thread->task_queue[UNTIED_IDX(victim)]));
          task = NULL;
        }
        */
        return task;
      }
    }
  }

  /* if no task in local queue and no available untied tasks, we will look in
   * another queue so long as there are no suspended tasks tied to thread and
   * the current task is either in a barrier or its not tied
   */
CHECK_TIED_TASK_QUEUES:
  if (task == NULL && !current_thread->num_suspended_tied_tasks &&
      (__ompc_task_state_is_in_barrier(current_task) ||
       !__ompc_task_is_tied(current_task))) {
    int first_victim, victim = 0;
    int team_size = pool->team_size;

    victim = (rand_r(&__omp_seed) % (team_size - 1));
    if (victim >= myid) victim++;
    /* cycle through to find a queue with work to steal */
    first_victim = victim;
    while (1) {
      while (__ompc_queue_is_empty(
                         &per_thread->task_queue[TIED_IDX(victim)])) {
        victim++;
        if (victim == myid)
          victim++;
        if (victim == team_size)
          victim = 0;
        if (victim == first_victim)
          return NULL;
      }
      /* Always steal from the head for tied tasks. Note also that by not
       * using the task_queue API, CFIFO implementation will not be used */
      task = __ompc_queue_steal_head(
                         &per_thread->task_queue[TIED_IDX(victim)]);
      if ( task != NULL ) {
        /*
        if (!__ompc_task_state_is_unscheduled(task)) {
          // Is_True(0, ("state of task from queue was not unscheduled"));
          printf("\n... (2) skipping over a task with state %s; queue size is %d \n",
                  __ompc_task_get_state_string(task),
         __ompc_queue_num_used_slots(&per_thread->task_queue[TIED_IDX(victim)]));
          task = NULL;
        }
        */
        return task;
      }
    }
  }

  /*
  if ( task != NULL ) {
    if (!__ompc_task_state_is_unscheduled(task)) {
      // Is_True(0, ("state of task from queue was not unscheduled"));
      printf("\n... (3) skipping over a task with state %s; queue size is %d \n",
          __ompc_task_get_state_string(task),
          __ompc_queue_num_used_slots(&per_thread->task_queue[UNTIED_IDX(myid)]));
      task = NULL;
    }
  }
  */
  return task;
}
コード例 #3
0
/* __ompc_remove_task_from_pool_simple:
 * Takes a task from the task pool. First tries to get a task from the current
 * thread's task queue. If that doesn't work, then it will attempt to steal a
 * task from another task queue (so long as there are no other tasks, not in a
 * barrier, that are tied to the current thread).
 *
 * Note: The restriction on stealing is overly conservative. Even if there are
 * tasks tied to the current thread and not in a barrier ([*]), we should be
 * able to steal any untied tasks, or tied tasks that descend from all tasks
 * in [*]. But this implementation does not separate untied tasks from tied
 * tasks, and also does not track descendants in the task pool.
 */
omp_task_t *__ompc_remove_task_from_pool_simple(omp_task_pool_t *pool)
{
  omp_task_t *task, *current_task;
  omp_team_t *team;
  omp_v_thread_t *current_thread;
  omp_queue_t *my_queue;
  omp_queue_t *victim_queue;
  omp_task_queue_level_t *per_thread;
  int myid = __omp_myid;
  int team_size;

  Is_True(pool != NULL, ("__ompc_remove_task_from_pool: task pool is uninitialized"));

  current_task = __omp_current_task;
  current_thread = __omp_current_v_thread;
  per_thread = &pool->level[PER_THREAD];

  task = __ompc_task_queue_get(&per_thread->task_queue[myid]);

  /* if no task in local queue, we will look in another queue so long as there
   * are no suspended tasks tied to thread and the current task is either in a
   * barrier or its not tied
   */
  team_size = pool->team_size;
  if (task == NULL && (team_size > 1) &&
      !current_thread->num_suspended_tied_tasks &&
      (__ompc_task_state_is_in_barrier(current_task) ||
       !__ompc_task_is_tied(current_task))) {
    int first_victim, victim = 0, go_right;
    go_right = (rand_r(&__omp_seed) % (2));
    victim = (rand_r(&__omp_seed) % (team_size - 1));
    if (victim >= myid) victim++;
    first_victim = victim;
    if (go_right) {
      /* cycle through to find a queue with work to steal */
      while (1) {
        while (__ompc_queue_is_empty(&per_thread->task_queue[victim])) {
          victim++;
          if (victim == myid)
            victim++;
          if (victim == team_size)
            victim = 0;
          if (victim == first_victim)
            return NULL;
        }
        task = __ompc_task_queue_steal(&per_thread->task_queue[victim]);
        if ( task != NULL ) return task;
      }
    } else {
      /* cycle through to find a queue with work to steal */
      while (1) {
        while (__ompc_queue_is_empty(&per_thread->task_queue[victim])) {
          victim--;
          if (victim == myid)
            victim--;
          if (victim == -1)
            victim = team_size-1;
          if (victim == first_victim)
            return NULL;
        }
        task = __ompc_task_queue_steal(&per_thread->task_queue[victim]);
        if ( task != NULL ) return task;
      }
    }
  }

  return task;
}