/* ** 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; }
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; }
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; }
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; }
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; }