NNModule_(NNModule* o) : o_(o), context_(getGlobalContext()), module_("NNModule", context_), builder_(context_){ _mutex.lock(); if(!_initialized){ InitializeNativeTarget(); _initialized = true; } _mutex.unlock(); engine_ = EngineBuilder(&module_).setUseMCJIT(true).create(); TypeVec args; args.push_back(doubleType()); createExtern("llvm.exp.f64", doubleType(), args); }
MStatus dynExprField::compute(const MPlug& plug, MDataBlock& block) // // Descriptions: // compute output force. // { MStatus status; if( !(plug == mOutputForce) ) return( MS::kUnknownParameter ); // get the logical index of the element this plug refers to. // int multiIndex = plug.logicalIndex( &status ); McheckErr(status, "ERROR in plug.logicalIndex.\n"); // Get input data handle, use outputArrayValue since we do not // want to evaluate both inputs, only the one related to the // requested multiIndex. Evaluating both inputs at once would cause // a dependency graph loop. MArrayDataHandle hInputArray = block.outputArrayValue( mInputData, &status ); McheckErr(status,"ERROR in hInputArray = block.outputArrayValue().\n"); status = hInputArray.jumpToElement( multiIndex ); McheckErr(status, "ERROR: hInputArray.jumpToElement failed.\n"); // get children of aInputData. MDataHandle hCompond = hInputArray.inputValue( &status ); McheckErr(status, "ERROR in hCompond=hInputArray.inputValue\n"); MDataHandle hPosition = hCompond.child( mInputPositions ); MObject dPosition = hPosition.data(); MFnVectorArrayData fnPosition( dPosition ); MVectorArray points = fnPosition.array( &status ); McheckErr(status, "ERROR in fnPosition.array(), not find points.\n"); // Comment out the following since velocity, and mass are // not needed in this field. // // MDataHandle hVelocity = hCompond.child( mInputVelocities ); // MObject dVelocity = hVelocity.data(); // MFnVectorArrayData fnVelocity( dVelocity ); // MVectorArray velocities = fnVelocity.array( &status ); // McheckErr(status, "ERROR in fnVelocity.array(), not find velocities.\n"); // // MDataHandle hMass = hCompond.child( mInputMass ); // MObject dMass = hMass.data(); // MFnDoubleArrayData fnMass( dMass ); // MDoubleArray masses = fnMass.array( &status ); // McheckErr(status, "ERROR in fnMass.array(), not find masses.\n"); // The attribute mInputPPData contains the attribute in an array form // parpared by the particleShape if the particleShape has per particle // attribute fieldName_attrName. // // Suppose a field with the name dynExprField1 is connecting to // particleShape1, and the particleShape1 has per particle float attribute // dynExprField1_magnitude and vector attribute dynExprField1_direction, // then hInputPPArray will contains a MdoubleArray with the corresponding // name "magnitude" and a MvectorArray with the name "direction". This // is a mechanism to allow the field attributes being driven by dynamic // expression. MArrayDataHandle mhInputPPData = block.inputArrayValue( mInputPPData, &status ); McheckErr(status,"ERROR in mhInputPPData = block.inputArrayValue().\n"); status = mhInputPPData.jumpToElement( multiIndex ); McheckErr(status, "ERROR: mhInputPPArray.jumpToElement failed.\n"); MDataHandle hInputPPData = mhInputPPData.inputValue( &status ); McheckErr(status, "ERROR in hInputPPData = mhInputPPData.inputValue\n"); MObject dInputPPData = hInputPPData.data(); MFnArrayAttrsData inputPPArray( dInputPPData ); MDataHandle hOwnerPPData = block.inputValue( mOwnerPPData, &status ); McheckErr(status, "ERROR in hOwnerPPData = block.inputValue\n"); MObject dOwnerPPData = hOwnerPPData.data(); MFnArrayAttrsData ownerPPArray( dOwnerPPData ); const MString magString("magnitude"); MFnArrayAttrsData::Type doubleType(MFnArrayAttrsData::kDoubleArray); bool arrayExist; MDoubleArray magnitudeArray; arrayExist = inputPPArray.checkArrayExist(magString, doubleType, &status); // McheckErr(status, "ERROR in checkArrayExist(magnitude)\n"); if(arrayExist) { magnitudeArray = inputPPArray.getDoubleData(magString, &status); // McheckErr(status, "ERROR in inputPPArray.doubleArray(magnitude)\n"); } MDoubleArray magnitudeOwnerArray; arrayExist = ownerPPArray.checkArrayExist(magString, doubleType, &status); // McheckErr(status, "ERROR in checkArrayExist(magnitude)\n"); if(arrayExist) { magnitudeOwnerArray = ownerPPArray.getDoubleData(magString, &status); // McheckErr(status, "ERROR in ownerPPArray.doubleArray(magnitude)\n"); } const MString dirString("direction"); MFnArrayAttrsData::Type vectorType(MFnArrayAttrsData::kVectorArray); arrayExist = inputPPArray.checkArrayExist(dirString, vectorType, &status); MVectorArray directionArray; // McheckErr(status, "ERROR in checkArrayExist(direction)\n"); if(arrayExist) { directionArray = inputPPArray.getVectorData(dirString, &status); // McheckErr(status, "ERROR in inputPPArray.vectorArray(direction)\n"); } arrayExist = ownerPPArray.checkArrayExist(dirString, vectorType, &status); MVectorArray directionOwnerArray; // McheckErr(status, "ERROR in checkArrayExist(direction)\n"); if(arrayExist) { directionOwnerArray = ownerPPArray.getVectorData(dirString, &status); // McheckErr(status, "ERROR in ownerPPArray.vectorArray(direction)\n"); } // Compute the output force. // MVectorArray forceArray; apply( block, points.length(), magnitudeArray, magnitudeOwnerArray, directionArray, directionOwnerArray, forceArray ); // get output data handle // MArrayDataHandle hOutArray = block.outputArrayValue( mOutputForce, &status); McheckErr(status, "ERROR in hOutArray = block.outputArrayValue.\n"); MArrayDataBuilder bOutArray = hOutArray.builder( &status ); McheckErr(status, "ERROR in bOutArray = hOutArray.builder.\n"); // get output force array from block. // MDataHandle hOut = bOutArray.addElement(multiIndex, &status); McheckErr(status, "ERROR in hOut = bOutArray.addElement.\n"); MFnVectorArrayData fnOutputForce; MObject dOutputForce = fnOutputForce.create( forceArray, &status ); McheckErr(status, "ERROR in dOutputForce = fnOutputForce.create\n"); // update data block with new output force data. // hOut.set( dOutputForce ); block.setClean( plug ); return( MS::kSuccess ); }
bool compile(const nstr& name, NNet& network, size_t threads){ RunNetwork* runNetwork = new RunNetwork; NNet::Layer* inputLayer = network.layer(0); size_t numLayers = network.numLayers(); RunLayer* lastRunLayer = 0; for(size_t l = 1; l < numLayers; ++l){ RunLayer* runLayer = new RunLayer; runLayer->queue = new Queue(threads); size_t inputLayerSize = inputLayer->size(); NNet::Layer* layer = network.layer(l); size_t layerSize = layer->size(); if(l > 1){ runLayer->inputVecStart = lastRunLayer->outputVecStart; runLayer->inputVec = lastRunLayer->outputVec; } if(l < numLayers - 1){ double* outputVecPtrStart; double* outputVecPtr; allocVector(layerSize, &outputVecPtrStart, &outputVecPtr); runLayer->outputVecStart = outputVecPtrStart; runLayer->outputVec = outputVecPtr; } TypeVec args; args.push_back(getPointer(doubleVecType(inputLayerSize))); args.push_back(getPointer(doubleVecType(inputLayerSize))); args.push_back(getPointer(doubleType())); args.push_back(int32Type()); FunctionType* ft = FunctionType::get(voidType(), args, false); Function* f = Function::Create(ft, Function::ExternalLinkage, name.c_str(), &module_); BasicBlock* entry = BasicBlock::Create(context_, "entry", f); builder_.SetInsertPoint(entry); auto aitr = f->arg_begin(); Value* inputVecPtr = aitr; inputVecPtr->setName("input_vec_ptr"); ++aitr; Value* weightVecPtr = aitr; weightVecPtr->setName("weight_vec_ptr"); ++aitr; Value* outputVecPtr = aitr; outputVecPtr->setName("output_vec_ptr"); ++aitr; Value* outputIndex = aitr; outputIndex->setName("output_index"); Value* inputVec = builder_.CreateLoad(inputVecPtr, "input_vec"); Value* weightVec = builder_.CreateLoad(weightVecPtr, "weight_vec"); Value* mulVec = builder_.CreateFMul(inputVec, weightVec, "mul_vec"); Value* sumActivation = builder_.CreateExtractElement(mulVec, getInt32(0), "sum_elem"); for(size_t i = 1; i < inputLayerSize; ++i){ Value* elem = builder_.CreateExtractElement(mulVec, getInt32(i), "sum_elem"); sumActivation = builder_.CreateFAdd(sumActivation, elem, "sum_activation"); } Value* output = getActivationOutput(layer->neuron(0), sumActivation); Value* outputElement = builder_.CreateGEP(outputVecPtr, outputIndex, "out_elem"); builder_.CreateStore(output, outputElement); builder_.CreateRetVoid(); runLayer->f = f; runLayer->fp = (void (*)(void*, void*, void*, int)) engine_->getPointerToFunction(f); for(size_t j = 0; j < layerSize; ++j){ NNet::Neuron* nj = layer->neuron(j); RunNeuron* runNeuron = new RunNeuron; runNeuron->layer = runLayer; runNeuron->outputIndex = j; double* weightVecPtrStart; double* weightVecPtr; allocVector(inputLayerSize, &weightVecPtrStart, &weightVecPtr); runNeuron->weightVecStart = weightVecPtrStart; runNeuron->weightVec = weightVecPtr; for(size_t i = 0; i < inputLayerSize; ++i){ NNet::Neuron* ni = inputLayer->neuron(i); weightVecPtr[i] = nj->weight(ni); } runLayer->queue->add(runNeuron); } runNetwork->layerVec.push_back(runLayer); inputLayer = layer; lastRunLayer = runLayer; } networkMap_.insert(make_pair(name, runNetwork)); return true; }
VectorType* doubleVecType(size_t length){ return VectorType::get(doubleType(), length); }