| 795 | } |
| 796 | |
| 797 | void* Variable::readInternal(bool forShape) { |
| 798 | if (nullptr == mFrom->get()) { |
| 799 | if (VARP::INPUT == mFrom->mType) { |
| 800 | if (mFrom->mInside->mContentDirty) { |
| 801 | return nullptr; |
| 802 | } |
| 803 | } |
| 804 | //MNN_ASSERT(nullptr != mFrom->inside()->mOutputTensors[0]->buffer().host); |
| 805 | auto inside = mFrom->inside(); |
| 806 | auto originTensor = inside->mOutputTensors[mFromIndex]; |
| 807 | auto des = TensorUtils::getDescribe(originTensor); |
| 808 | if (WrapExecution::needWrap(originTensor, nullptr) || (des->quantAttr != nullptr && des->applyQuant)) { |
| 809 | // For StaticModule will other-device runtime, we may create Variable with other-device's memory |
| 810 | // The case won't occurred for varibale = INPUT |
| 811 | // Need Copy |
| 812 | if (nullptr != inside->mHostTensor) { |
| 813 | // The Varp will not be created as input, so we just need copy once |
| 814 | return inside->mHostTensor->host<void>(); |
| 815 | } |
| 816 | |
| 817 | inside->mHostTensor = new Tensor; |
| 818 | TensorUtils::copyShape(originTensor, inside->mHostTensor, true); |
| 819 | inside->mHostTensor->buffer().type = originTensor->getType(); |
| 820 | inside->mHostTensor->buffer().host = (uint8_t*)MNNMemoryAllocAlign(inside->mHostTensor->size(), MNN_MEMORY_ALIGN_DEFAULT); |
| 821 | TensorUtils::getDescribe(inside->mHostTensor)->memoryType = Tensor::InsideDescribe::MEMORY_HOST; |
| 822 | originTensor->copyToHostTensor(inside->mHostTensor); |
| 823 | bool hasNoExecution = false; |
| 824 | if (nullptr != originTensor) { |
| 825 | auto backend = TensorUtils::getDescribeOrigin(originTensor)->getBackend(); |
| 826 | if (nullptr != backend) { |
| 827 | // Try to sync to check execution status |
| 828 | int syncResult = backend->onSync(Tensor::MAP_TENSOR_READ, false, originTensor); |
| 829 | if (NO_EXECUTION == syncResult) { |
| 830 | hasNoExecution = true; |
| 831 | } |
| 832 | } |
| 833 | } |
| 834 | if (hasNoExecution) { |
| 835 | MNN_PRINT("\nWarning, Backend has stop execute, return nullptr for current varp\n"); |
| 836 | return nullptr; |
| 837 | } |
| 838 | return inside->mHostTensor->host<void>(); |
| 839 | } |
| 840 | return originTensor->buffer().host; |
| 841 | } |
| 842 | auto res = mFrom->requireInfo(); |
| 843 | if (false == res) { |
| 844 | return nullptr; |
| 845 | } |
| 846 | auto cache = mFrom->inside()->mCache; |
| 847 | if (nullptr == cache) { |
| 848 | ExecutorScope::Current()->makeCache({mFrom}, forShape); |
| 849 | cache = mFrom->inside()->mCache; |
| 850 | } |
| 851 | if (nullptr == cache) { |
| 852 | return nullptr; |
| 853 | } |
| 854 | if (NO_ERROR != cache->compute()) { |
no test coverage detected