196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet/* 296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * Copyright (C) 2017 The Android Open Source Project 396775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * 496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * Licensed under the Apache License, Version 2.0 (the "License"); 596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * you may not use this file except in compliance with the License. 696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * You may obtain a copy of the License at 796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * 896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * http://www.apache.org/licenses/LICENSE-2.0 996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * 1096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * Unless required by applicable law or agreed to in writing, software 1196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * distributed under the License is distributed on an "AS IS" BASIS, 1296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1396775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * See the License for the specific language governing permissions and 1496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * limitations under the License. 1596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet */ 1696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 1796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet#define LOG_TAG "ModelBuilder" 1896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 1996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet#include "ModelBuilder.h" 2096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 2183e24dc4706a5b7089881a55daf05b3924fab3b7David Gross#include "CompilationBuilder.h" 2296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet#include "Utils.h" 2396775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 2496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet#include <map> 2596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet#include <utility> 2696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 2796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouilletnamespace android { 2896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouilletnamespace nn { 2996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 30c1ab6fc5e953a61811e9f25d2afff06bfa571f0eJean-Luc Brouillet// The maximum number of operands and operations that a model may have. 31c1ab6fc5e953a61811e9f25d2afff06bfa571f0eJean-Luc Brouilletconst uint32_t MAX_NUMBER_OF_OPERANDS = 0xFFFFFFFE; 32c1ab6fc5e953a61811e9f25d2afff06bfa571f0eJean-Luc Brouilletconst uint32_t MAX_NUMBER_OF_OPERATIONS = 0xFFFFFFFE; 33c1ab6fc5e953a61811e9f25d2afff06bfa571f0eJean-Luc Brouillet 3496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouilletint ModelBuilder::addOperand(const ANeuralNetworksOperandType& type) { 3596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet if (mCompletedModel) { 36544739620cd7f37d40524d2407c92042e485c73fDavid Gross LOG(ERROR) << "ANeuralNetworksModel_addOperand can't modify after model finished"; 3796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 3896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet } 39e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet int n = validateOperandType(type, "ANeuralNetworksModel_addOperand", true); 40e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet if (n != ANEURALNETWORKS_NO_ERROR) { 41e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet return n; 42e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet } 43707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet size_t idx = mOperands.size(); 4496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet if (idx >= MAX_NUMBER_OF_OPERANDS) { 45707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksModel_addOperand exceed max operands"; 4696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 4796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet } 4896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet mOperands.resize(idx + 1); 49a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet auto& operand = mOperands[idx]; 50a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet operand.type = static_cast<OperandType>(type.type); 51d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet setFromIntList(&operand.dimensions, type.dimensionCount, type.dimensions); 52a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet operand.numberOfConsumers = 0; 53a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet operand.scale = type.scale; 54a5c16e4e73a34e6776a8f071ab884444c28b6893Miao Wang operand.zeroPoint = type.zeroPoint; 55a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet operand.lifetime = OperandLifeTime::TEMPORARY_VARIABLE; 56a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet operand.location = {.poolIndex = 0, .offset = 0, .length = 0}; 5796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 5896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet} 5996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 6096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouilletint ModelBuilder::setOperandValue(uint32_t index, const void* buffer, size_t length) { 611da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet VLOG(MODEL) << __func__ << " for operand " << index << " size " << length; 6296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet if (index >= operandCount()) { 63707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksModel_setOperandValue setting operand " << index << " of " 64707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet << operandCount(); 6596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 6696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet } 67707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet Operand& operand = mOperands[index]; 6862cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet if (buffer == nullptr) { 6962cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet if (length) { 7062cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksModel_setOperandValue buffer is nullptr but length is " 7162cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet "not 0"; 7262cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 7362cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet } 7462cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet operand.lifetime = OperandLifeTime::NO_VALUE; 7562cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet // The location is unused and is set to zeros. 7662cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet operand.location = {.poolIndex = 0, 7762cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet .offset = 0, 7862cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet .length = 0}; 7962cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet } else { 801da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet if (length > 0xFFFFFFFF) { 811da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksModel_setOperandValue value length of " << length 821da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet << " exceeds max size"; 831da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 841da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet } 851da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet uint32_t valueLength = static_cast<uint32_t>(length); 8662cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet uint32_t neededLength = sizeOfData(operand.type, operand.dimensions); 871da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet if (neededLength != valueLength) { 881da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksModel_setOperandValue setting " << valueLength 8962cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet << " bytes when needing " << neededLength; 9062cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 9162cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet } 921da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet if (valueLength <= ANEURALNETWORKS_MAX_SIZE_OF_IMMEDIATELY_COPIED_VALUES) { 931da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet uint32_t existingSize = static_cast<uint32_t>(mSmallOperandValues.size()); 941da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet uint32_t extraBytes = alignBytesNeeded(existingSize, valueLength); 951da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet mSmallOperandValues.resize(existingSize + extraBytes + valueLength); 961da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet operand.lifetime = OperandLifeTime::CONSTANT_COPY; 971da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet operand.location = { 981da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet .poolIndex = 0, .offset = existingSize + extraBytes, .length = neededLength}; 991da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet memcpy(&mSmallOperandValues[operand.location.offset], buffer, valueLength); 1001da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet VLOG(MODEL) << "Copied small value to offset " << operand.location.offset; 1011da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet } else { 1021da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet VLOG(MODEL) << "Saving large value"; 1031da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet operand.lifetime = OperandLifeTime::CONSTANT_REFERENCE; 1041da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet // The values for poolIndex and offset will be set when the model is finished. 1051da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet operand.location = {.poolIndex = 0, .offset = 0, .length = valueLength}; 1061da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet // We keep track of the buffers. We'll allocate the shared memory only 1071da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet // once we know the total size, to avoid needless copies. 1081da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet mLargeOperandValues.push_back(LargeValue{.operandIndex = index, .buffer = buffer}); 1091da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet } 1101da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet } 1111da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 1121da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet} 1131da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet 1141da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouilletint ModelBuilder::copyLargeValuesToSharedMemory() { 1151da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet VLOG(MODEL) << __func__ << " has " << mLargeOperandValues.size() << " values."; 1161da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet if (!mLargeOperandValues.empty()) { 1171da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet // Calculate the size of the shared memory needed for all the large values. 1181da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet // Also sets the offset for each value within the memory. 1191da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet size_t poolSize = 0; 1201da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet for (LargeValue& l: mLargeOperandValues) { 1211da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet Operand& operand = mOperands[l.operandIndex]; 1221da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet nnAssert(operand.lifetime == OperandLifeTime::CONSTANT_REFERENCE); 1231da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet poolSize += alignBytesNeeded(poolSize, operand.location.length); 1241da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet operand.location.offset = poolSize; 1251da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet poolSize += operand.location.length; 1261da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet } 1271da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet 1281da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet // Allocated the shared memory. 1291da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet int n = mLargeValueMemory.create(poolSize); 1301da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet if (n != ANEURALNETWORKS_NO_ERROR) { 1311da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet return n; 1321da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet } 1331da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet uint8_t* memoryPointer = nullptr; 1341da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet n = mLargeValueMemory.getPointer(&memoryPointer); 1351da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet if (n != ANEURALNETWORKS_NO_ERROR) { 1361da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet return n; 1371da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet } 1381da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet uint32_t poolIndex = mMemories.add(&mLargeValueMemory); 1391da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet VLOG(MODEL) << "Allocated large value pool of size " << poolSize << " at index " 1401da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet << poolIndex; 1411da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet 1421da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet // Copy the values to this memory. 1431da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet for (LargeValue& l: mLargeOperandValues) { 1441da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet Operand& operand = mOperands[l.operandIndex]; 1451da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet operand.location.poolIndex = poolIndex; 1461da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet memcpy(memoryPointer + operand.location.offset, l.buffer, operand.location.length); 1471da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet } 14896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet } 14996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 15096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet} 15196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 1528b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouilletint ModelBuilder::setOperandValueFromMemory(uint32_t index, const Memory* memory, uint32_t offset, 1538b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet size_t length) { 1541da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet VLOG(MODEL) << __func__ << " for operand " << index << " offset " << offset << " size " << length; 1558b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (index >= operandCount()) { 1568b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksModel_setOperandValueFromMemory setting operand " << index 1578b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet << " of " << operandCount(); 1588b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 1598b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 1608b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet Operand& operand = mOperands[index]; 1618b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet uint32_t neededLength = sizeOfData(operand.type, operand.dimensions); 1628b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (neededLength != length) { 1638b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksModel_setOperandValueFromMemory setting " << length 1648b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet << " bytes when needing " << neededLength; 1658b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 1668b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 1678b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet // TODO validate does not exceed length of memory 168a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet operand.lifetime = OperandLifeTime::CONSTANT_REFERENCE; 169d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet operand.location = { 170d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet .poolIndex = mMemories.add(memory), .offset = offset, .length = neededLength}; 1718b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 1728b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet} 1738b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet 174d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouilletint ModelBuilder::addOperation(ANeuralNetworksOperationType type, uint32_t inputCount, 175d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet const uint32_t* inputs, uint32_t outputCount, 176d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet const uint32_t* outputs) { 17796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet if (mCompletedModel) { 178544739620cd7f37d40524d2407c92042e485c73fDavid Gross LOG(ERROR) << "ANeuralNetworksModel_addOperation can't modify after model finished"; 17996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 18096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet } 181e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet if (!validCode(kNumberOfOperationTypes, kNumberOfOperationTypesOEM, type)) { 182e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksModel_addOperation invalid operations type " << type; 183e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 184e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet } 185e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet int n = validateOperandList(inputCount, inputs, operandCount(), 186e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet "ANeuralNetworksModel_addOperation inputs"); 187e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet if (n != ANEURALNETWORKS_NO_ERROR) { 188e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet return n; 189e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet } 190e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet n = validateOperandList(outputCount, outputs, operandCount(), 191e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet "ANeuralNetworksModel_addOperation outputs"); 192e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet if (n != ANEURALNETWORKS_NO_ERROR) { 193e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet return n; 194e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet } 195e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet 19696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet uint32_t operationIndex = operationCount(); 19796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet if (operationIndex >= MAX_NUMBER_OF_OPERATIONS) { 198707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksModel_addOperation exceed max operations"; 19996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 20096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet } 20196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet mOperations.resize(operationIndex + 1); 20296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet auto& entry = mOperations[operationIndex]; 2037d6ac906f000f3afe418e92c0a4ae36b2ea1143eJean-Luc Brouillet entry.type = static_cast<OperationType>(type); 20496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 205d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet setFromIntList(&entry.inputs, inputCount, inputs); 206d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet setFromIntList(&entry.outputs, outputCount, outputs); 207707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet for (uint32_t i : entry.inputs) { 208707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet mOperands[i].numberOfConsumers++; 209707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet // TODO mOperands[i].consumers.push_back(operationIndex); 21096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet } 21196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 21296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet} 21396775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 21466d5cb6e3a90aefc8d545f6369080ab88de9d667Jean-Luc Brouilletint ModelBuilder::identifyInputsAndOutputs(uint32_t inputCount, const uint32_t* inputs, 215d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet uint32_t outputCount, const uint32_t* outputs) { 21696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet if (mCompletedModel) { 21766d5cb6e3a90aefc8d545f6369080ab88de9d667Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksModel_identifyInputsAndOutputs can't modify after model finished"; 21896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 21996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet } 220e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet int n = validateOperandList(inputCount, inputs, operandCount(), 22166d5cb6e3a90aefc8d545f6369080ab88de9d667Jean-Luc Brouillet "ANeuralNetworksModel_identifyInputsAndOutputs inputs"); 222e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet if (n != ANEURALNETWORKS_NO_ERROR) { 223e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet return n; 224e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet } 225e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet n = validateOperandList(outputCount, outputs, operandCount(), 22666d5cb6e3a90aefc8d545f6369080ab88de9d667Jean-Luc Brouillet "ANeuralNetworksModel_identifyInputsAndOutputs outputs"); 227e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet if (n != ANEURALNETWORKS_NO_ERROR) { 228e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet return n; 229e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet } 230a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet 231a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet // Makes a copy of the index list, validates the arguments, and changes 232a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet // the lifetime info of the corresponding operand. 233d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet auto setArguments = [&](std::vector<uint32_t>* indexVector, uint32_t indexCount, 234d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet const uint32_t* indexList, OperandLifeTime lifetime) -> bool { 235d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet indexVector->resize(indexCount); 236d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet for (uint32_t i = 0; i < indexCount; i++) { 237d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet const uint32_t operandIndex = indexList[i]; 238a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet if (operandIndex >= mOperands.size()) { 23966d5cb6e3a90aefc8d545f6369080ab88de9d667Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksModel_identifyInputsAndOutputs Can't set input or output " 240a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet "to be " 241a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet << operandIndex << " as this exceeds the numbe of operands " 242a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet << mOperands.size(); 243a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet return false; 244a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet } 245a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet (*indexVector)[i] = operandIndex; 246a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet Operand& operand = mOperands[operandIndex]; 247a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet if (operand.lifetime != OperandLifeTime::TEMPORARY_VARIABLE) { 24866d5cb6e3a90aefc8d545f6369080ab88de9d667Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksModel_identifyInputsAndOutputs Can't set operand " 249a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet << operandIndex 250a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet << " to be an input or output. Check that it's not a constant or " 251a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet "already an input or output"; 252a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet return false; 253a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet } 254a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet operand.lifetime = lifetime; 255a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet } 256a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet return true; 257a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet }; 258a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet 259d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet if (!setArguments(&mInputIndexes, inputCount, inputs, OperandLifeTime::MODEL_INPUT) || 260d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet !setArguments(&mOutputIndexes, outputCount, outputs, OperandLifeTime::MODEL_OUTPUT)) { 261a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 262a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet } 263a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet 26496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 26596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet} 26696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 267544739620cd7f37d40524d2407c92042e485c73fDavid Grossint ModelBuilder::createCompilation(CompilationBuilder** compilation) { 268544739620cd7f37d40524d2407c92042e485c73fDavid Gross if (!mCompletedModel) { 269544739620cd7f37d40524d2407c92042e485c73fDavid Gross LOG(ERROR) << "ANeuralNetworksCompilation_create passed an unfinished model"; 270544739620cd7f37d40524d2407c92042e485c73fDavid Gross *compilation = nullptr; 271544739620cd7f37d40524d2407c92042e485c73fDavid Gross return ANEURALNETWORKS_BAD_STATE; 272544739620cd7f37d40524d2407c92042e485c73fDavid Gross } 273544739620cd7f37d40524d2407c92042e485c73fDavid Gross *compilation = new CompilationBuilder(this); 274544739620cd7f37d40524d2407c92042e485c73fDavid Gross return (*compilation ? ANEURALNETWORKS_NO_ERROR : ANEURALNETWORKS_OUT_OF_MEMORY); 27596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet} 27696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 277544739620cd7f37d40524d2407c92042e485c73fDavid Grossint ModelBuilder::finish() { 278544739620cd7f37d40524d2407c92042e485c73fDavid Gross if (mCompletedModel) { 279544739620cd7f37d40524d2407c92042e485c73fDavid Gross LOG(ERROR) << "ANeuralNetworksModel_finish called more than once"; 280544739620cd7f37d40524d2407c92042e485c73fDavid Gross return ANEURALNETWORKS_BAD_STATE; 28196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet } 282544739620cd7f37d40524d2407c92042e485c73fDavid Gross 2831da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet int n = copyLargeValuesToSharedMemory(); 2841da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet if (n != ANEURALNETWORKS_NO_ERROR) { 2851da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet return n; 2861da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet } 2871da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet 288544739620cd7f37d40524d2407c92042e485c73fDavid Gross // We sort the operations so that they will be in the appropriate 289544739620cd7f37d40524d2407c92042e485c73fDavid Gross // order for a single-threaded, op at a time execution. 2901da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet // TODO: we don't need this if we always run the partitioner. 291544739620cd7f37d40524d2407c92042e485c73fDavid Gross sortIntoRunOrder(); 292544739620cd7f37d40524d2407c92042e485c73fDavid Gross mCompletedModel = true; 293544739620cd7f37d40524d2407c92042e485c73fDavid Gross return ANEURALNETWORKS_NO_ERROR; 29496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet} 29596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 29696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouilletvoid ModelBuilder::sortIntoRunOrder() { 29796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet // Tracks the operations that can be executed. 29896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet std::vector<uint32_t> opsReadyToRun; 299707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet std::vector<Operation> runOrder; 30096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 30196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet // Tracks how many inputs are needed for each operation to be ready to run. 30296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet std::multimap<uint32_t, uint32_t> operandToOperations; 30396775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet std::vector<uint32_t> unknownInputCount(operationCount()); 30496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet for (uint32_t operationIndex = 0; operationIndex < operationCount(); operationIndex++) { 30596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet uint32_t& count = unknownInputCount[operationIndex]; 30696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet count = 0; 307707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet for (uint32_t operandIndex : mOperations[operationIndex].inputs) { 308a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet auto lifetime = mOperands[operandIndex].lifetime; 309a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet if (lifetime == OperandLifeTime::TEMPORARY_VARIABLE || 310a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet lifetime == OperandLifeTime::MODEL_OUTPUT) { 31196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet count++; 31296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet operandToOperations.insert( 313d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet std::pair<uint32_t, uint32_t>(operandIndex, operationIndex)); 31496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet } 31596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet } 31696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet if (count == 0) { 31796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet opsReadyToRun.push_back(operationIndex); 31896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet } 31996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet } 32096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 32196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet while (opsReadyToRun.size() > 0) { 32296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet // Execute the next op 32396775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet int opIndex = opsReadyToRun.back(); 32496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet opsReadyToRun.pop_back(); 325707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet const Operation& operation = mOperations[opIndex]; 32696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 32796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet runOrder.push_back(mOperations[opIndex]); 32896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 329a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet // Mark all its outputs as known. 330707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet for (uint32_t operandIndex : operation.outputs) { 33196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet auto range = operandToOperations.equal_range(operandIndex); 33296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet for (auto i = range.first; i != range.second; i++) { 33396775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet uint32_t& count = unknownInputCount[i->second]; 33496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet if (--count == 0) { 33596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet opsReadyToRun.push_back(i->second); 33696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet } 33796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet } 33896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet } 33996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet } 34096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet mOperations = runOrder; 34196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet} 34296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 343707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletvoid ModelBuilder::setHidlModel(Model* model) const { 344707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet model->operands = mOperands; 345707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet model->operations = mOperations; 346707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet model->inputIndexes = mInputIndexes; 347707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet model->outputIndexes = mOutputIndexes; 3481da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet model->operandValues = mSmallOperandValues; 3498b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet 3508b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet uint32_t count = mMemories.size(); 3518b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet model->pools.resize(count); 3528b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (uint32_t i = 0; i < count; i++) { 3538b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet model->pools[i] = mMemories[i]->getHidlMemory(); 3548b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 35596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet} 35696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet 357d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet} // namespace nn 358d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet} // namespace android 359