// f_parallel_for
//  begin - start of range to process
//	end - 1 after end of range to process
//  func - worker function of the form worker($begin, $end, $inputdata) - returns an array of max length ($end-$begin)
//  blocksize - optional blocksize, refer to TBB documentation
// Returns: array of maximum length ($end-$begin)
//
// Call 'func' for non-overlapping array segments to cover all of arraydata
// This will use threads as appropriate for the machine.
// If a result is returned by 'func' it will be placed into the result array elements corresponding to the input elements
Variant f_parallel_for_array(CVarRef arraydata, CVarRef func, int64 blocksize /* = -1 */) {
	if(!arraydata.isArray())
	{
		raise_error("parallel_for_array expected an array in first argument");
		return Variant();
	}

	// Get the input array
	const Array aArray = arraydata.asCArrRef();
	ArrayData *pdArray = aArray.getArrayData();

	size_t asize = pdArray->size();
	if(asize==0)
		return Variant();

	MemoryManager *mm = MemoryManager::TheMemoryManager().get();
	if (RuntimeOption::CheckMemory) {
	    mm->checkMemory(false);
	  }

    TbbContext myContext  = TbbContext::Entry("parallel_for_array");

    std::vector<Variant> outArray;
    outArray.resize(asize);

    // Construct task parameters
	PforTaskParameters tclass = PforTaskParameters(myContext, pdArray, func, &outArray);

    TbbInitializeIfNeeded();

    if (blocksize == -1) {
            // Use auto_partitioner for block size
            tbb::parallel_for(tbb::blocked_range<int64>(0, asize), tclass, tbb::auto_partitioner());
    } else {
            // Use manually set block size
            tbb::parallel_for(tbb::blocked_range<int64>(0, asize, blocksize), tclass);
    }

    myContext.Exit();


    // Create the result array
	Array resPHPArray = Array::Create();
	for(size_t ai=0; ai<outArray.size(); ai++) {
		Variant amem = outArray[ai];
		// printf(" ai=%d, append %s\n", (int)ai, amem.toString().c_str());
		if(!amem.isNull())
			resPHPArray.append(amem);
	}

	if(resPHPArray.size()==0)
		return Variant();		// i.e null

	return resPHPArray.getArrayData();
}
Beispiel #2
0
void Globals::initialize() {
  StaticInits *s = s_next_inits;
  while (s) {
    const ClassPropTable *cpt = s->table;
    const int *e = s->entries;
    int n = *e++;
    while (n--) {
      const ClassPropTableEntry *p = cpt->m_entries + *e++;
      char *addr = (char*)this + p->offset;
      if (LIKELY(p->isFastInit())) {
        CVarRef v = cpt->getInitV(p->init_offset);
        switch (p->type) {
          case KindOfBoolean:
            *(bool*)addr = v.asBooleanVal();
            break;
          case KindOfInt64:
            *(int64*)addr = v.asInt64Val();
            break;
          case KindOfDouble:
            *(double*)addr = v.asDoubleVal();
            break;
          case KindOfString:
            *(String*)addr = v.asCStrRef();
            break;
          case KindOfArray:
            *(Array*)addr = v.asCArrRef();
            break;
          case KindOfVariant:
            *(Variant*)addr = v;
            break;
          default:
            ASSERT(false);
        }
        continue;
      }
      CVarRef v = cpt->getInitVal(p);
      if (LIKELY(p->type == KindOfVariant)) {
        *(Variant*)addr = v;
      } else {
        switch (p->type) {
          case KindOfBoolean:
            *(bool*)addr = v;
            break;
          case KindOfInt64:
            *(int64*)addr = v;
            break;
          case KindOfDouble:
            *(double*)addr = v;
            break;
          case KindOfString:
            *(String*)addr = v;
            break;
          case KindOfArray:
            *(Array*)addr = v;
            break;
          default:
            ASSERT(false);
        }
      }
    }
    s = s->next;
  }
}