ncFifoReadElem()

Info Value
Header mvnc.h
Library libmvnc.so
Version 2.0
See also struct ncFifoHandle_t, ncGraphQueueInference()

Overview

This function reads an element from a FIFO, usually the result of an inference, along with the associated user-defined data that was passed to ncGraphQueueInferenceWithFifoElem() or ncFifoWriteElem().

This will also remove the element from the queue.

Prototype

ncStatus_t ncFifoReadElem(struct ncFifoHandle_t* fifoHandle, void* outputData,
                          unsigned int* outputDataLen, void** userParam);

Parameters

Name Type Description
fifo struct ncFifoHandle_t* A pointer to the ncFifoHandle_t struct for the FIFO. The FIFO state must be NC_FIFO_ALLOCATED.
outputData void* A pointer to a buffer into which the result of the inference will be copied. The buffer will contain data in the format specified by the FIFO’s NC_RW_FIFO_DATA_TYPE option.
outputDataLen unsigned int* A pointer to an unsigned int that contains the size, in bytes, of the buffer allocated to the outputData parameter.

Upon normal return (status code NC_OK), the unsigned int pointed to by dataLength will be set to the number of bytes copied to the data buffer. In the event that the data buffer was an insufficient size to hold the outputData, the return status code will be NC_INVALID_DATA_LENGTH and the unsigned int pointed to by dataLength will be set to the size required.
userParam void** Address of a pointer that will be set to point to the user-defined data for this inference. This corresponds to the userParam that was passed when data was written to the input FIFO with ncGraphQueueInferenceWithFifoElem() or ncFifoWriteElem().

Return

An appropriate value from the ncStatus_t enumeration.

Notes

  • The ncFifoType_t set during FIFO creation must allow read access for the API.
  • The FIFO can not be written to or read from until it has been allocated with ncGraphAllocateWithFifos()/ncGraphAllocateWithFifosEx() or ncFifoAllocate().
  • The API can only read each element once even if NC_RW_FIFO_CONSUMER_COUNT is greater than 1.
  • This is a blocking call if NC_RW_FIFO_DONT_BLOCK is false. If the FIFO is empty this function will not return until there is an element to read.
    • You can check the current fill level of the FIFO with ncFifoGetOption() for NC_RO_FIFO_READ_FILL_LEVEL.
    • After an inference is queued there is a delay while device communication occurs and the inference is performed before the element is removed from the input FIFO and placed into the output FIFO.
  • If you don’t know what value to use for outputDataLen, you can call this function once with an outputDataLen of 0 to have outputDataLen be set to the correct value, and then call this function again to get the output result in outputData.

Example

#include <stdio.h>
#include <stdlib.h>
#include <mvnc.h>

int main(int argc, char** argv)
{
    float networkMean[] = {0.40787054*255.0, 0.45752458*255.0, 0.48109378*255.0};
    ncStatus_t retCode;
    struct ncDeviceHandle_t* deviceHandlePtr = NULL;
    struct ncGraphHandle_t* graphHandlePtr = NULL;
    struct ncFifoHandle_t* inFifoHandlePtr = NULL;
    struct ncFifoHandle_t* outFifoHandlePtr = NULL;
    struct ncTensorDescriptor_t inTensorDesc;
    struct ncTensorDescriptor_t outTensorDesc;
    float* imageInMemoryPtr = NULL;
    unsigned int optionSize;

    ncDeviceCreate(0, &deviceHandlePtr);
    ncDeviceOpen(deviceHandlePtr);
    ncGraphCreate("My Graph", &graphHandlePtr);
    
    unsigned int graphSizeInBytes = 0;
    void* graphInMemoryPtr = LoadGraphFile("./graph", &graphSizeInBytes);
    ncGraphAllocate(deviceHandlePtr, graphHandlePtr, graphInMemoryPtr, graphSizeInBytes);
    free(graphInMemoryPtr);

    ncFifoCreate("MY Input FIFO", NC_FIFO_HOST_WO, &inFifoHandlePtr);
    optionSize = sizeof(ncTensorDescriptor_t);
    ncGraphGetOption(graphHandlePtr, NC_RO_GRAPH_INPUT_TENSOR_DESCRIPTORS, &inTensorDesc, &optionSize);
    ncFifoAllocate(inFifoHandlePtr, deviceHandlePtr, &inTensorDesc, 2);
    
    ncFifoCreate("MY Output FIFO", NC_FIFO_HOST_RO, &outFifoHandlePtr);
    optionSize = sizeof(ncTensorDescriptor_t);
    ncGraphGetOption(graphHandlePtr, NC_RO_GRAPH_OUTPUT_TENSOR_DESCRIPTORS, &outTensorDesc, &optionSize);
    ncFifoAllocate(outFifoHandlePtr, deviceHandlePtr, &outTensorDesc, 2);

    unsigned int networkDim = 224;
    unsigned int numChannels = 3;
    imageInMemoryPtr = LoadImage32("./my_image.png", networkDim, networkMean);
    imageSize = sizeof(float) * networkDim * networkDim * numChannels;
    ncFifoWriteElem(inFifoHandlePtr, imageInMemoryPtr, &imageSize, 0);
    free(imageInMemoryPtr);

    ncGraphQueueInference(graphHandlePtr, &inFifoHandlePtr, 1, &outFifoHandlePtr, 1);

    void* outputPtr = NULL;
    unsigned int fifoOutputSize = 0;
    unsigned int optionDataLen = sizeof(unsigned int);
    ncFifoGetOption(outFifoHandlePtr, NC_RO_FIFO_ELEMENT_DATA_SIZE, &fifoOutputSize, &optionDataLen);
    outputPtr = malloc(fifoOutputSize);
    ncFifoReadElem(outFifoHandlePtr, outputPtr, &fifoOutputSize, NULL);
    if (retCode != NC_OK)
    {   // Could not read FIFO element
        printf("Error reading FIFO element [%d]\n", retCode);
    }
    else
    {   // outputPtr now points to the result of the inference
        printf("Successfully read FIFO element\n");        
    }
    
    // use the output, then free it
    free(outputPtr);
    outputPtr = NULL;
    
    // clean up the graph and device
    ncFifoDestroy(&inFifoHandlePtr);
    ncFifoDestroy(&outFifoHandlePtr);
    ncGraphDestroy(&graphHandlePtr);
    ncDeviceClose(deviceHandlePtr);
    ncDeviceDestroy(&deviceHandlePtr);
}