Beispiel #1
0
/*
** this is the core of the worker threads: as long as there are bins
** left to process, get the next one, and process it
*/
int
_pullProcess(pullTask *task) {
  char me[]="_pullProcess", err[BIFF_STRLEN];
  unsigned int binIdx;

  task->stuckNum = 0;
  while (task->pctx->binNextIdx < task->pctx->binNum) {
    /* get the index of the next bin to process */
    if (task->pctx->threadNum > 1) {
      airThreadMutexLock(task->pctx->binMutex);
    }
    /* note that we entirely skip bins with no points */
    do {
      binIdx = task->pctx->binNextIdx;
      if (task->pctx->binNextIdx < task->pctx->binNum) {
        task->pctx->binNextIdx++;
      }
    } while (binIdx < task->pctx->binNum
             && 0 == task->pctx->bin[binIdx].pointNum);
    if (task->pctx->threadNum > 1) {
      airThreadMutexUnlock(task->pctx->binMutex);
    }
    if (binIdx == task->pctx->binNum) {
      /* no more bins to process! */
      break;
    }
    if (pullBinProcess(task, binIdx)) {
      sprintf(err, "%s(%u): had trouble on bin %u", me,
              task->threadIdx, binIdx);
      biffAdd(PULL, err); return 1;
    }
  }
  return 0;
}
/*
** this is run once per task (thread), per stage
*/
int
_pushStageRun(pushTask *task, int stageIdx) {
  char me[]="_pushStageRun", err[BIFF_STRLEN];
  unsigned int binIdx;
  
  while (task->pctx->binIdx < task->pctx->numBin) {
    if (task->pctx->numThread > 1) {
      airThreadMutexLock(task->pctx->binMutex);
    }
    do {
      binIdx = task->pctx->binIdx;
      if (task->pctx->binIdx < task->pctx->numBin) {
        task->pctx->binIdx++;
      }
    } while (binIdx < task->pctx->numBin
             && 0 == task->pctx->bin[binIdx].numThing
             && 0 == task->pctx->bin[binIdx].numPoint);
    if (task->pctx->numThread > 1) {
      airThreadMutexUnlock(task->pctx->binMutex);
    }

    if (binIdx == task->pctx->numBin) {
      /* no more bins to process */
      break;
    }

    if (task->pctx->process[stageIdx](task, binIdx,
                                      task->pctx->stageParm[stageIdx])) {
      sprintf(err, "%s(%d): had trouble running stage %d", me,
              task->threadIdx, stageIdx);
      biffAdd(PUSH, err); return 1;
    }
  }
  return 0;
}
Beispiel #3
0
int
_coilThisZGet(coilTask *task, int doFilter) {
  int thisZ, *thisFlag, *thatFlag;

  if (doFilter) {
    thisFlag = &(task->cctx->todoFilter);
    thatFlag = &(task->cctx->todoUpdate);
  } else {
    thisFlag = &(task->cctx->todoUpdate);
    thatFlag = &(task->cctx->todoFilter);
  }

  if (task->cctx->numThreads > 1) {
    airThreadMutexLock(task->cctx->nextSliceMutex);
  }
  if (task->cctx->nextSlice == task->cctx->size[2]
      && *thisFlag) {
    /* we're the first thread to start this phase */
    task->cctx->nextSlice = 0;
    *thisFlag = AIR_FALSE;
  }
  thisZ = task->cctx->nextSlice;
  if (task->cctx->nextSlice < task->cctx->size[2]) {
    task->cctx->nextSlice++;
    if (task->cctx->nextSlice == task->cctx->size[2]) {
      /* we just grabbed the last slice of this phase */
      *thatFlag = AIR_TRUE;
    }
  }
  if (task->cctx->numThreads > 1) {
    airThreadMutexUnlock(task->cctx->nextSliceMutex);
  }
  return thisZ;
}
Beispiel #4
0
int
airThreadBarrierWait(airThreadBarrier *barrier) {

  airThreadMutexLock(barrier->doneMutex);
  barrier->numDone += 1;
  if (barrier->numDone < barrier->numUsers) {
    airThreadCondWait(barrier->doneCond, barrier->doneMutex);
  } else {
    barrier->numDone = 0;
    airThreadCondBroadcast(barrier->doneCond);
  }
  airThreadMutexUnlock(barrier->doneMutex);
  return 0;
}
Beispiel #5
0
void *
_hooverThreadBody(void *_arg) {
  _hooverThreadArg *arg;
  void *thread;
  int ret,               /* to catch return values from callbacks */
    sampleI,             /* which sample we're on */
    inside,              /* we're inside the volume */
    vI, uI;              /* integral coords in image */
  double tmp,
    mm,                  /* lowest position in index space, for all axes */
    Mx, My, Mz,          /* highest position in index space on each axis */
    u, v,                /* floating-point coords in image */
    uvScale,             /* how to scale (u,v) to go from image to 
                            near plane, according to ortho or perspective */
    lx, ly, lz,          /* half edge-lengths of volume */
    rayLen=0,            /* length of segment formed by ray line intersecting
                            the near and far clipping planes */
    rayT,                /* current position along ray (world-space) */
    rayDirW[3],          /* unit-length ray direction (world-space) */
    rayDirI[3],          /* rayDirW transformed into index space;
                            not unit length, but a unit change in
                            world space along rayDirW translates to
                            this change in index space along rayDirI */
    rayPosW[3],          /* current ray location (world-space) */
    rayPosI[3],          /* current ray location (index-space) */
    rayStartW[3],        /* ray start on near plane (world-space) */
    rayStartI[3],        /* ray start on near plane (index-space) */
    rayStep,             /* distance between samples (world-space) */
    vOff[3], uOff[3];    /* offsets in arg->ec->wU and arg->ec->wV
                            directions towards start of ray */

  arg = (_hooverThreadArg *)_arg;
  if ( (ret = (arg->ctx->threadBegin)(&thread, 
                                      arg->render, 
                                      arg->ctx->user,
                                      arg->whichThread)) ) {
    arg->errCode = ret;
    arg->whichErr = hooverErrThreadBegin;
    return arg;
  }
  lx = arg->ec->volHLen[0];
  ly = arg->ec->volHLen[1];
  lz = arg->ec->volHLen[2];
  if (nrrdCenterNode == arg->ctx->volCentering) {
    mm = 0;
    Mx = arg->ctx->volSize[0]-1;
    My = arg->ctx->volSize[1]-1;
    Mz = arg->ctx->volSize[2]-1;
  } else {
    mm = -0.5;
    Mx = arg->ctx->volSize[0]-0.5;
    My = arg->ctx->volSize[1]-0.5;
    Mz = arg->ctx->volSize[2]-0.5;
  }
  
  if (arg->ctx->cam->orthographic) {
    ELL_3V_COPY(rayDirW, arg->ctx->cam->N);
    rayDirI[0] = AIR_DELTA(-lx, rayDirW[0], lx, mm, Mx);
    rayDirI[1] = AIR_DELTA(-ly, rayDirW[1], ly, mm, My);
    rayDirI[2] = AIR_DELTA(-lz, rayDirW[2], lz, mm, Mz);
    rayLen = arg->ctx->cam->vspFaar - arg->ctx->cam->vspNeer;
    uvScale = 1.0;
  } else {
    uvScale = arg->ctx->cam->vspNeer/arg->ctx->cam->vspDist;
  }

  while (1) {
    /* the work assignment is simply the next scanline to be rendered:
       the result of all this is setting vI */
    if (arg->ctx->workMutex) {
      airThreadMutexLock(arg->ctx->workMutex);
    }
    vI = arg->ctx->workIdx;
    if (arg->ctx->workIdx < arg->ctx->imgSize[1]) {
      arg->ctx->workIdx += 1;
    }
    if (arg->ctx->workMutex) {
      airThreadMutexUnlock(arg->ctx->workMutex);
    }
    if (vI == arg->ctx->imgSize[1]) {
      /* we're done! */
      break;
    }

    if (nrrdCenterCell == arg->ctx->imgCentering) {
      v = uvScale*AIR_AFFINE(-0.5, vI, arg->ctx->imgSize[1]-0.5,
                             arg->ctx->cam->vRange[0],
                             arg->ctx->cam->vRange[1]);
    } else {
      v = uvScale*AIR_AFFINE(0.0, vI, arg->ctx->imgSize[1]-1.0,
                             arg->ctx->cam->vRange[0],
                             arg->ctx->cam->vRange[1]);
    }
    ELL_3V_SCALE(vOff, v, arg->ctx->cam->V);
    for (uI=0; uI<arg->ctx->imgSize[0]; uI++) {
      if (nrrdCenterCell == arg->ctx->imgCentering) {
        u = uvScale*AIR_AFFINE(-0.5, uI, arg->ctx->imgSize[0]-0.5,
                               arg->ctx->cam->uRange[0],
                               arg->ctx->cam->uRange[1]);
      } else {
        u = uvScale*AIR_AFFINE(0.0, uI, arg->ctx->imgSize[0]-1.0,
                               arg->ctx->cam->uRange[0],
                               arg->ctx->cam->uRange[1]);
      }
      ELL_3V_SCALE(uOff, u, arg->ctx->cam->U);
      ELL_3V_ADD3(rayStartW, uOff, vOff, arg->ec->rayZero);
      rayStartI[0] = AIR_AFFINE(-lx, rayStartW[0], lx, mm, Mx);
      rayStartI[1] = AIR_AFFINE(-ly, rayStartW[1], ly, mm, My);
      rayStartI[2] = AIR_AFFINE(-lz, rayStartW[2], lz, mm, Mz);
      if (!arg->ctx->cam->orthographic) {
        ELL_3V_SUB(rayDirW, rayStartW, arg->ctx->cam->from);
        ELL_3V_NORM(rayDirW, rayDirW, tmp);
        rayDirI[0] = AIR_DELTA(-lx, rayDirW[0], lx, mm, Mx);
        rayDirI[1] = AIR_DELTA(-ly, rayDirW[1], ly, mm, My);
        rayDirI[2] = AIR_DELTA(-lz, rayDirW[2], lz, mm, Mz);
        rayLen = ((arg->ctx->cam->vspFaar - arg->ctx->cam->vspNeer)/
                  ELL_3V_DOT(rayDirW, arg->ctx->cam->N));
      }
      if ( (ret = (arg->ctx->rayBegin)(thread,
                                       arg->render,
                                       arg->ctx->user,
                                       uI, vI, rayLen,
                                       rayStartW, rayStartI,
                                       rayDirW, rayDirI)) ) {
        arg->errCode = ret;
        arg->whichErr = hooverErrRayBegin;
        return arg;
      }
      
      sampleI = 0;
      rayT = 0;
      while (1) {
        ELL_3V_SCALE_ADD2(rayPosW, 1.0, rayStartW, rayT, rayDirW);
        ELL_3V_SCALE_ADD2(rayPosI, 1.0, rayStartI, rayT, rayDirI);
        inside = (AIR_IN_CL(mm, rayPosI[0], Mx) &&
                  AIR_IN_CL(mm, rayPosI[1], My) &&
                  AIR_IN_CL(mm, rayPosI[2], Mz));
        rayStep = (arg->ctx->sample)(thread,
                                     arg->render,
                                     arg->ctx->user,
                                     sampleI, rayT,
                                     inside,
                                     rayPosW, rayPosI);
        if (!AIR_EXISTS(rayStep)) {
          /* sampling failed */
          arg->errCode = 0;
          arg->whichErr = hooverErrSample;
          return arg;
        }
        if (!rayStep) {
          /* ray decided to finish itself */
          break;
        } 
        /* else we moved to a new location along the ray */
        rayT += rayStep;
        if (!AIR_IN_CL(0, rayT, rayLen)) {
          /* ray stepped outside near-far clipping region, its done. */
          break;
        }
        sampleI++;
      }
      
      if ( (ret = (arg->ctx->rayEnd)(thread,
                                     arg->render,
                                     arg->ctx->user)) ) {
        arg->errCode = ret;
        arg->whichErr = hooverErrRayEnd;
        return arg;
      }
    }  /* end this scanline */
  } /* end while(1) assignment of scanlines */

  if ( (ret = (arg->ctx->threadEnd)(thread,
                                    arg->render,
                                    arg->ctx->user)) ) {
    arg->errCode = ret;
    arg->whichErr = hooverErrThreadEnd;
    return arg;
  }
  
  /* returning NULL actually indicates that there was NOT an error */
  return NULL;
}
Beispiel #6
0
void *
_alanTuringWorker(void *_task) {
  alan_t *tendata, *ten, react,
    conf, Dxx, Dxy, Dyy, /* Dxz, Dyz, */
    *tpx, *tmx, *tpy, *tmy, /* *tpz, *tmz, */
    *lev0, *lev1, *parm, deltaT, alpha, beta, A, B,
    *v[27], lapA, lapB, corrA, corrB, 
    deltaA, deltaB, diffA, diffB, change;
  int dim, iter, stop, startW, endW, idx,
    px, mx, py, my, pz, mz,
    startY, endY, startZ, endZ, sx, sy, sz, x, y, z;
  alanTask *task;

  task = (alanTask *)_task;
  dim = task->actx->dim;
  sx = task->actx->size[0];
  sy = task->actx->size[1];
  sz = (2 == dim ? 1 : task->actx->size[2]);
  parm = (alan_t*)(task->actx->nparm->data);
  diffA = AIR_CAST(alan_t, task->actx->diffA/pow(task->actx->deltaX, dim));
  diffB = AIR_CAST(alan_t, task->actx->diffB/pow(task->actx->deltaX, dim));
  startW = task->idx*sy/task->actx->numThreads;
  endW = (task->idx+1)*sy/task->actx->numThreads;
  tendata = task->actx->nten ? (alan_t *)task->actx->nten->data : NULL;
  react = task->actx->react;

  if (2 == dim) {
    startZ = 0;
    endZ = 1;
    startY = startW;
    endY = endW;
  } else {
    startZ = startW;
    endZ = endW;
    startY = 0;
    endY = sy;
  }

  for (iter = 0; 
       (alanStopNot == task->actx->stop 
        && (0 == task->actx->maxIteration
            || iter < task->actx->maxIteration)); 
       iter++) {

    if (0 == task->idx) {
      task->actx->iter = iter;
      task->actx->nlev = task->actx->_nlev[(iter+1) % 2];
    }
    lev0 = (alan_t*)(task->actx->_nlev[iter % 2]->data);
    lev1 = (alan_t*)(task->actx->_nlev[(iter+1) % 2]->data);
    stop = alanStopNot;
    change = 0;
    conf = 1;  /* if you have no data; this will stay 1 */
    for (z = startZ; z < endZ; z++) {
      if (task->actx->wrap) {
        pz = AIR_MOD(z+1, sz);
        mz = AIR_MOD(z-1, sz);
      } else {
        pz = AIR_MIN(z+1, sz-1);
        mz = AIR_MAX(z-1, 0);
      }
      for (y = startY; y < endY; y++) {
        if (task->actx->wrap) {
          py = AIR_MOD(y+1, sy);
          my = AIR_MOD(y-1, sy);
        } else {
          py = AIR_MIN(y+1, sy-1);
          my = AIR_MAX(y-1, 0);
        }
        for (x = 0; x < sx; x++) {
          if (task->actx->wrap) {
            px = AIR_MOD(x+1, sx);
            mx = AIR_MOD(x-1, sx);
          } else {
            px = AIR_MIN(x+1, sx-1);
            mx = AIR_MAX(x-1, 0);
          }
          idx = x + sx*(y + sy*z);
          A = lev0[0 + 2*idx];
          B = lev0[1 + 2*idx];
          deltaT = parm[0 + 3*idx];
          alpha = parm[1 + 3*idx];
          beta = parm[2 + 3*idx];
          lapA = lapB = corrA = corrB = 0;
          if (2 == dim) {
            /*
            **  0 1 2 ----> X
            **  3 4 5
            **  6 7 8
            **  |
            **  v Y
            */
            v[1] = lev0 + 2*( x + sx*(my));
            v[3] = lev0 + 2*(mx + sx*( y));
            v[5] = lev0 + 2*(px + sx*( y));
            v[7] = lev0 + 2*( x + sx*(py));
            if (tendata) {
              /*
              **  0 1 2    Dxy/2          Dyy        -Dxy/2
              **  3 4 5     Dxx     -2*(Dxx + Dyy)     Dxx
              **  6 7 8   -Dxy/2          Dyy         Dxy/2
              */
              v[0] = lev0 + 2*(mx + sx*(my));
              v[2] = lev0 + 2*(px + sx*(my));
              v[6] = lev0 + 2*(mx + sx*(py));
              v[8] = lev0 + 2*(px + sx*(py));
              ten = tendata + 4*idx;
              conf = AIR_CAST(alan_t, (AIR_CLAMP(0.3, ten[0], 1) - 0.3)/0.7);
              if (conf) {
                Dxx = ten[1];
                Dxy = ten[2];
                Dyy = ten[3];
                lapA = (Dxy*(v[0][0] + v[8][0] - v[2][0] - v[6][0])/2
                        + Dxx*(v[3][0] + v[5][0]) + Dyy*(v[1][0] + v[7][0])
                        - 2*(Dxx + Dyy)*A);
                lapB = (Dxy*(v[0][1] + v[8][1] - v[2][1] - v[6][1])/2
                        + Dxx*(v[3][1] + v[5][1]) + Dyy*(v[1][1] + v[7][1])
                        - 2*(Dxx + Dyy)*B);
                if (!(task->actx->homogAniso)) {
                  tpx = tendata + 4*(px + sx*( y + sy*( z)));
                  tmx = tendata + 4*(mx + sx*( y + sy*( z)));
                  tpy = tendata + 4*( x + sx*(py + sy*( z)));
                  tmy = tendata + 4*( x + sx*(my + sy*( z)));
                  corrA = ((tpx[1]-tmx[1])*(v[5][0]-v[3][0])/4+ /* Dxx,x*A,x */
                           (tpx[2]-tmx[2])*(v[7][0]-v[1][0])/4+ /* Dxy,x*A,y */
                           (tpy[2]-tmy[2])*(v[5][0]-v[3][0])/4+ /* Dxy,y*A,x */
                           (tpy[3]-tmy[3])*(v[7][0]-v[1][0]));  /* Dyy,y*A,y */
                  corrB = ((tpx[1]-tmx[1])*(v[5][1]-v[3][1])/4+ /* Dxx,x*B,x */
                           (tpx[2]-tmx[2])*(v[7][1]-v[1][1])/4+ /* Dxy,x*B,y */
                           (tpy[2]-tmy[2])*(v[5][1]-v[3][1])/4+ /* Dxy,y*B,x */
                           (tpy[3]-tmy[3])*(v[7][1]-v[1][1]));  /* Dyy,y*B,y */
                }
              } else {
                /* no confidence; you diffuse */
                lapA = v[1][0] + v[3][0] + v[5][0] + v[7][0] - 4*A;
                lapB = v[1][1] + v[3][1] + v[5][1] + v[7][1] - 4*B;
              }
            } else {
              /* no data; you diffuse */
              lapA = v[1][0] + v[3][0] + v[5][0] + v[7][0] - 4*A;
              lapB = v[1][1] + v[3][1] + v[5][1] + v[7][1] - 4*B;
            }
          } else {
            /* 3 == dim */
            /*
            **          0   1   2   ---- X
            **        3   4   5
            **      6   7   8
            **    /
            **  /       9  10  11
            ** Y     12  13  14
            **     15  16  17
            **
            **         18  19  20
            **       21  22  23
            **     24  25  26
            **         |
            **         |
            **         Z
            */
            v[ 4] = lev0 + 2*( x + sx*( y + sy*(mz)));
            v[10] = lev0 + 2*( x + sx*(my + sy*( z)));
            v[12] = lev0 + 2*(mx + sx*( y + sy*( z)));
            v[14] = lev0 + 2*(px + sx*( y + sy*( z)));
            v[16] = lev0 + 2*( x + sx*(py + sy*( z)));
            v[22] = lev0 + 2*( x + sx*( y + sy*(pz)));
            if (tendata) {

              if (!(task->actx->homogAniso)) {
                
              }
            } else {
              lapA = (v[ 4][0] + v[10][0] + v[12][0]
                      + v[14][0] + v[16][0] + v[22][0] - 6*A);
              lapB = (v[ 4][1] + v[10][1] + v[12][1]
                      + v[14][1] + v[16][1] + v[22][1] - 6*B);
            }
          }
          
          deltaA = deltaT*(react*conf*task->actx->K*(alpha - A*B) 
                           + diffA*(lapA + corrA));
          if (AIR_ABS(deltaA) > task->actx->maxPixelChange) {
            stop = alanStopDiverged;
          }
          change += AIR_ABS(deltaA);
          deltaB = deltaT*(react*conf*task->actx->K*(A*B - B - beta)
                           + diffB*(lapB + corrB));
          if (!( AIR_EXISTS(deltaA) && AIR_EXISTS(deltaB) )) {
            stop = alanStopNonExist;
          }
          
          A += deltaA;
          B = AIR_MAX(0, B + deltaB);
          lev1[0 + 2*idx] = A;
          lev1[1 + 2*idx] = B; 
        }
      }
    }
    
    /* add change to global sum in a threadsafe way */
    airThreadMutexLock(task->actx->changeMutex);
    task->actx->averageChange += change/(sx*sy*sz);
    task->actx->changeCount += 1;
    if (task->actx->changeCount == task->actx->numThreads) {
      /* I must be the last thread to reach this point; all 
         others must have passed the mutex unlock, and are
         sitting at the barrier */
      if (alanStopNot != stop) {
        /* there was some problem in going from lev0 to lev1, which
           we deal with now by setting actx->stop */
        task->actx->stop = stop;
      } else if (task->actx->averageChange < task->actx->minAverageChange) {
        /* we converged */
        task->actx->stop = alanStopConverged;
      } else {
        /* we keep going */
        _alanPerIteration(task->actx, iter);
        if (task->actx->perIteration) {
          task->actx->perIteration(task->actx, iter);
        }
      }
      task->actx->averageChange = 0;
      task->actx->changeCount = 0;
    }
    airThreadMutexUnlock(task->actx->changeMutex);

    /* force all threads to line up here, once per iteration */
    airThreadBarrierWait(task->actx->iterBarrier);
  }
  
  if (iter == task->actx->maxIteration) {
    /* HEY: all threads will agree on this, right? */
    task->actx->stop = alanStopMaxIteration;
  }
  /* else: the non-alanStopNot value of task->actx->stop made us stop */
  return _task;
}