// Runs forward propagation of activations on the input line. // See NetworkCpp for a detailed discussion of the arguments. void Parallel::Forward(bool debug, const NetworkIO& input, const TransposedArray* input_transpose, NetworkScratch* scratch, NetworkIO* output) { bool parallel_debug = false; // If this parallel is a replicator of convolvers, or holds a 1-d LSTM pair, // or a 2-d LSTM quad, do debug locally, and don't pass the flag on. if (debug && type_ != NT_PARALLEL) { parallel_debug = true; debug = false; } int stack_size = stack_.size(); if (type_ == NT_PAR_2D_LSTM) { // Special case, run parallel in parallel. GenericVector<NetworkScratch::IO> results; results.init_to_size(stack_size, NetworkScratch::IO()); for (int i = 0; i < stack_size; ++i) { results[i].Resize(input, stack_[i]->NumOutputs(), scratch); } #ifdef _OPENMP #pragma omp parallel for num_threads(stack_size) #endif for (int i = 0; i < stack_size; ++i) { stack_[i]->Forward(debug, input, nullptr, scratch, results[i]); } // Now pack all the results (serially) into the output. int out_offset = 0; output->Resize(*results[0], NumOutputs()); for (int i = 0; i < stack_size; ++i) { out_offset = output->CopyPacking(*results[i], out_offset); } } else { // Revolving intermediate result. NetworkScratch::IO result(input, scratch); // Source for divided replicated. NetworkScratch::IO source_part; TransposedArray* src_transpose = nullptr; if (IsTraining() && type_ == NT_REPLICATED) { // Make a transposed copy of the input. input.Transpose(&transposed_input_); src_transpose = &transposed_input_; } // Run each network, putting the outputs into result. int out_offset = 0; for (int i = 0; i < stack_size; ++i) { stack_[i]->Forward(debug, input, src_transpose, scratch, result); // All networks must have the same output width if (i == 0) { output->Resize(*result, NumOutputs()); } else { ASSERT_HOST(result->Width() == output->Width()); } out_offset = output->CopyPacking(*result, out_offset); } } if (parallel_debug) { DisplayForward(*output); } }
void CommandBase::PrintDetailedDescription(ostream& out) { out<<"-"<<Name()<<":"<<endl; out<<"Args:"<<endl; for(size_t i=0;i<args.size();i++) { switch(args[i].type) { case Bool: out<<"\tbool "<<args[i].name<<" (default "<<(*(bool*)(args[i].data) ? "true":"false")<<")"<<endl; break; case Int: out<<"\tint "<<args[i].name<<" (default "<<(*(int*)(args[i].data))<<")"<<endl; break; case Float: out<<"\tfloat "<<args[i].name<<" (default "<<(*(float*)(args[i].data))<<")"<<endl; break; case Double: out<<"\tdouble "<<args[i].name<<" (default "<<(*(double*)(args[i].data))<<")"<<endl; break; case String: out<<"\tstring "<<args[i].name<<" (default "<<(*(const char**)(args[i].data))<<")"<<endl; break; default: out<<"Error!"<<endl; break; } } if(MaxInputs() < 0) out<<"Inputs: at least "<<MinInputs()<<endl; else if(MaxInputs() == MinInputs()) out<<"Inputs: "<<MinInputs()<<endl; else out<<"Inputs: between "<<MinInputs()<<" and "<<MaxInputs()<<endl; out<<"Outputs: "<<NumOutputs()<<endl; out<<"Description: "; PrintDescription(out); }
bool CommandBase::ProcessLine() { assert(line != NULL); if(line->size() < NumArgs()) { cout<<"Not enough arguments to "<<Name()<<endl; return false; } int args_remaining = (int)line->size(); int j; for(j=0; j<NumArgs(); j++,args_remaining--) { if(!SetArg(j,(*line)[j])) { cout<<"Error reading argument "<<GetArgName(j)<<"="<<(*line)[j]<<" to "<<Name()<<endl; return false; } } int num_inputs = args_remaining - NumOutputs(); if(MaxInputs() >= 0) { if(num_inputs > MaxInputs()) { cout << "The number of max inputs to -" <<Name()<<" was exceeded."<<endl; return false; } } if(num_inputs < MinInputs()) { cout << "Not enough inputs given to -" <<Name()<<endl; return false; } inputs.resize(num_inputs); for(int i=0;i<num_inputs;i++,j++,args_remaining--) { inputs[i]=(*line)[j]; } assert(args_remaining == NumOutputs()); outputs.resize(NumOutputs()); for(int i=0;i<NumOutputs();i++,j++,args_remaining--) { outputs[i]=(*line)[j]; } assert(j == line->size()); assert(args_remaining == 0); return true; }
bool SVDF::Prepare(const Operation &operation, std::vector<RunTimeOperandInfo> &operands, Shape *stateShape, Shape *outputShape) { // Check we have all the inputs and outputs we need. const int num_inputs = NumInputsWithValues(operation, operands); NN_CHECK(num_inputs == 6 || num_inputs == 7); NN_CHECK_EQ(NumOutputs(operation), 2); const RunTimeOperandInfo *input = GetInput(operation, operands, SVDF::kInputTensor); const RunTimeOperandInfo *weights_feature = GetInput(operation, operands, SVDF::kWeightsFeatureTensor); const RunTimeOperandInfo *weights_time = GetInput(operation, operands, SVDF::kWeightsTimeTensor); // Check all the parameters of tensor match within themselves and match the // input configuration. const int rank = getScalarData<int>(*GetInput(operation, operands, kRankParam)); const uint32_t batch_size = SizeOfDimension(input, 0); const uint32_t num_filters = SizeOfDimension(weights_feature, 0); NN_CHECK_EQ(num_filters % rank, 0); const uint32_t num_units = num_filters / rank; const uint32_t memory_size = SizeOfDimension(weights_time, 1); NN_CHECK_EQ(SizeOfDimension(input, 1), SizeOfDimension(weights_feature, 1)); NN_CHECK_EQ(SizeOfDimension(weights_time, 0), num_filters); const RunTimeOperandInfo *bias = GetInput(operation, operands, kBiasTensor); if (!IsNullInput(bias)) { NN_CHECK_EQ(SizeOfDimension(bias, 0), num_units); } // Resize state. const Shape &inputShape = input->shape(); stateShape->type = inputShape.type; stateShape->dimensions = { batch_size, memory_size * num_filters }; stateShape->offset = inputShape.offset; stateShape->scale = inputShape.scale; // Resize output. outputShape->type = inputShape.type; outputShape->dimensions = { batch_size, num_units }; outputShape->offset = inputShape.offset; outputShape->scale = inputShape.scale; return true; }