o
    XiEJ                     @  sD  d Z ddlmZ ddlmZ g dZddlZddlZddlZddl	m
Z
mZ ddlmZmZmZ ddlmZ dd	lmZ d
ZdZdZeeZejG dd dZejG dd dZ	dIdJddZdKddZdLd!d"ZeeefdMd)d*Z dNd+d,Z!	dOdPd4d5Z"dQd9d:Z#dRd<d=Z$	dOdSd?d@Z%dTdCdDZ&dddEdUdGdHZ'dS )Vz External data related utilities.    )annotations)Callable)set_base_dirunload_from_modelload_to_modelconvert_tensors_to_externalconvert_tensors_from_externalCallbackInfoN)IteratorSequence)_core_enums
_protocols)	traversal)zipTi   i   c                   @  s*   e Zd ZU dZded< ded< ded< dS )_ExternalDataInfoaQ  A class that stores information about a tensor that is to be stored as external data.

    Attributes:
        name: The name of the tensor that is to be stored as external data.
        offset: The offset is used to determine where exactly in the file the external data is written to.
        length: Stores the size of the tensor.
    z
str | NonenameintoffsetlengthN__name__
__module____qualname____doc____annotations__ r   r   I/home/ubuntu/.local/lib/python3.10/site-packages/onnx_ir/external_data.pyr   '   s
   
 r   c                   @  s2   e Zd ZU dZded< ded< ded< ded< dS )	r	   ag  A class that shares information about a tensor that is to be saved as external data for callback functions.

    Attributes:
        total: The total number of tensors to save.
        index: The index of the tensor being saved.
        offset: The offset of the tensor in the external data file.
        filename: The filename of the external data file.
    r   totalindexr   strfilenameNr   r   r   r   r   r	   6   s   
 	r	   Fgraph_core.Graphinclude_attributesboolreturn#Iterator[_protocols.TensorProtocol]c                 c  s,   | j  D ]}|j }dur|V  q|sdS t| D ]w}|j D ]o}| r*q#|jtj	j
kr;|jdur;|jV  q#|jtj	jkrN|jdurN|jE dH  q#|jtj	jkrn|jdurn|jj  D ]}|j }durl|V  q`q#|jtj	jkr|jdur|jD ]}|j  D ]}|j }dur|V  qq}q#qdS )zIterate over all tensors in the graph.

    Args:
        graph: The graph to traverse tensors on.
        include_attributes: Whether to include tensors in attributes.

    Yields:
        Tensors in the graph.
    N)initializersvaluesconst_value
_traversalRecursiveGraphIterator
attributesis_reftyper   AttributeTypeTENSORvalueTENSORSGRAPHGRAPHS)r"   r$   r2   tensornodeattrgr   r   r   _all_tensorsG   s>   

r:   base_dirstr | os.PathLikeNonec                 C  s(   t | ddD ]}t|tjr||_qdS )zSet the base directory for external data in a graph (including all of its subgraphs).

    Args:
        graph: The graph to traverse tensors on.
        base_dir: The base directory. This is the directory where the ONNX file is.
    T)r$   N)r:   
isinstancer   ExternalTensorr;   )r"   r;   r6   r   r   r   r   m   s
   r   r6   _protocols.TensorProtocolc                 C  sF   t | tjstdt|  |   }|   tj|| j	| j
dS )aC  Convert an external tensor to an in memory tensor.

    Args:
        tensor: An external tensor to load.
        base_dir: Path of base directory.
        relative_path: Path to which external data is to be stored, relative to the ONNX file.

    Returns:
        An ir.Tensor object with the data loaded into memory.
    zExpected ExternalTensor, got )r   dtype)r>   r   r?   	TypeErrorr/   numpycopyreleaseTensorr   rA   )r6   tensor_datar   r   r   !_external_tensor_to_memory_tensory   s
   rH   current_offsetr   tensor_sizealign_offsetalign_thresholdallocation_granularityc                 C  s.   |r||krt d|}| | d | | S | S )ai  Compute the offset to align the tensor data based on the current offset.

    Args:
        current_offset: Current location in the file at which tensor data will be written to.
        tensor_size: Size of the tensor data to be written to file.
        align_offset: Offset will always be page aligned and alloction granularity aligned for mmap support. This is done by padding previous tensor data with zeros keeping same length. Tensor data will be aligned if > align_threshold
        align_threshold: Alignment threshold for size of data. Having a low threshold will waste file space for small initializers. Only when tensor's data is > the page_align_threshold it will be force aligned.
        allocation_granularity: The allocation Granularity for mmap() support. Typically 64KB for Windows & 4KB for other OSes.

    Returns:
        The updated offset value.
    i      )max)rI   rJ   rK   rL   rM   alignment_factorr   r   r   _compute_new_offset   s   
rQ   c                 C  s"   | j }t||}t| j||}|S )zICapture information about a tensor that is to be stored as external data.)nbytesrQ   r   r   )r6   rI   rJ   external_data_infor   r   r   _compute_external_data_info   s   
rT   tensors#Sequence[_protocols.TensorProtocol]external_data_infosSequence[_ExternalDataInfo]	file_pathcallback@Callable[[_protocols.TensorProtocol, CallbackInfo], None] | Nonec                 C  s  t | }|t |ksJ dt|de}tt| |ddD ]R\}\}}|dur7||t|||jtj|d |j}	|dus@J |	 }
|	|
krQ|
d|	|
   t|dr\|| q| }t|tjrj|  |
| qW d   dS 1 s{w   Y  dS )	a  Write tensor data to an external file according to information stored in ExternalDataInfo objects.

    Args:
        tensors: Tensors to be written as external data.
        external_data_infos: External data information stored for each tensor to be written as external data.
        file_path: Location to which external data is to be stored.
        callback: A callback function that is called for each tensor that is saved to external data
            for debugging or logging purposes.
    z6Number of tensors and external data infos should matchwbTstrictN)r   r   r   r!       tofile)lenopen	enumerater   r	   r   ospathbasenametellwritehasattrr`   tobytesr>   r   r?   rE   )rU   rW   rY   rZ   tensors_count	data_fileir6   tensor_inforI   	file_sizeraw_datar   r   r   _write_external_data   s>   
	
"rq   rS   relative_path_core.ExternalTensorc              
   C  s2   t jtj||j|j| j| j| j	tj|dS )a  Create external tensors from external data information.

    Args:
        tensor: Tensor to be converted to external tensor.
        external_data_info: External data information stored for the tensor to be written as external data.
        base_dir: Path of base directory.
        relative_path: Path to which external data is to be stored, relative to the ONNX file.

    Returns:
        External tensor created from the information.
    )shaper   r;   )
r   r?   rd   re   normpathr   r   rA   rt   r   )r6   rS   r;   rr   r   r   r   _create_external_tensor   s   

rv   list[_protocols.TensorProtocol]c                 C  s   dd | D S )zConvert a sequence of external tensors to in-memory tensors.

    Args:
        tensors: External tensors to be converted to in-memory tensors.

    Returns:
        A list of in-memory tensors derived from a list of external tensors.
    c                 S  s   g | ]}t |qS r   )rH   ).0r6   r   r   r   
<listcomp>      z1convert_tensors_from_external.<locals>.<listcomp>r   rU   r   r   r   r     s   r   list[_core.ExternalTensor]c                   s@  t j }t j|rBg }D ].}t|tjr:t j|jr:t j||jr:|t	| |
  td| q|| q|g }tttfdddfddD }d}	|D ]}t||	}
||
 |
j|
j }	q_t||||d  fd	dt||d
dD fddtttfdddD S )a  Convert a sequence of any TensorProtocol tensors to external tensors.

    Existing external tensors are loaded to memory if they are referring to the
    same file path as the destination path.

    Args:
        tensors: Tensors to be converted to external tensors. They can be external tensors themselves.
        base_dir: Path of base directory.
        relative_path: Path to which external data is to be stored, relative to the ONNX file.
        callback: A callback function that is called for each tensor that is saved to external data
            for debugging or logging purposes.

    Returns:
        A list of external tensors derived from a list of input tensors. The order
        should match the input tensor order.
    zExternal tensor %s is referring to the same file as the destination path. It has been invalidated because the data file is changed. To avoid this, save the external data to a different path or load the newly saved model back with ir.load().c                   s
    |  j S N)rR   rm   r{   r   r   <lambda>M  s   
 z-convert_tensors_to_external.<locals>.<lambda>)keyc                      g | ]} | qS r   r   rx   rm   r{   r   r   ry   N  rz   z/convert_tensors_to_external.<locals>.<listcomp>r   )rZ   c                   s   g | ]\}}t || qS r   )rv   )rx   r6   external_info)r;   rr   r   r   ry   Y  s    Tr]   c                   r   r   r   r   )external_tensorsr   r   ry   _  s    c                   s    |  S r}   r   r~   )sorted_indicesr   r   r   a  s    )rd   re   joinexistsr>   r   r?   samefileappendrH   
invalidateloggerwarningsortedrangera   rT   r   r   rq   r   )rU   r;   rr   rZ   re   new_tensorsr6   rW   sorted_tensorsrI   r   r   )r;   r   rr   r   rU   r   r     sD   



r   model_core.Modelc                 C  sz   g }|   D ]}|j D ]}|jdu rqt|jtjr!|| qqtdd |D }t	||ddD ]\}}||_q3| S )zConvert all external model initializers to memory tensors in-place.

    All initializers in the main graph and subgraphs are handled.

    Args:
        model: Model to process.
    Nc                 S     g | ]}|j qS r   r*   rx   vr   r   r   ry   y      z!load_to_model.<locals>.<listcomp>Tr]   )
graphsr(   r)   r*   r>   r   r?   r   r   r   )r   values_to_convertr"   r2   loaded_tensorsr6   r   r   r   r   g  s   	

r   )size_threshold_bytesrZ   r   c                C  s   g }g }|   D ](}|j D ] }|jdu rq|jj|kr#|| qt|jtjr/|| qqt	dd |D }	t
dd |D |||d}
t||
ddD ]\}}||_qNt||	ddD ]\}}||_q]| S )a  Convert all initializers equal or above size_threshold_bytes to external tensors in-place and save data to a single data file.

    It should only replace the initializers in the model with external tensors
    and not make any other modifications to the model.

    If any existing external tensor
    references the provided ``external_data`` path, it will be invalidated
    after the external data is overwritten. To obtain a valid model, use :func:`load`
    to load the newly saved model, or provide a different external data path that
    is not currently referenced by any tensors in the model.

    All initializers in the main graph and subgraphs are handled.

    Args:
        model: Model to process.
        base_dir: Path the directory where the ONNX model file is.
        relative_path: Path to which external data is to be stored, relative to the ONNX file.
            E.g. "model.data"
        size_threshold_bytes: Save to external data if the tensor size in bytes is larger than this threshold.
        callback: A callback function that is called for each tensor that is saved to external data
            for debugging or logging purposes.

    Returns:
        An ir.Model with all initializer data equal or above ``size_threshold_bytes``
        converted to external tensors.
    Nc                 S  r   r   r   r   r   r   r   ry     r   z%unload_from_model.<locals>.<listcomp>c                 S  r   r   r   r   r   r   r   ry     r   )r;   rr   rZ   Tr]   )r   r(   r)   r*   rR   r   r>   r   r?   r   r   r   )r   r;   rr   r   rZ   initializers_to_become_externalinitializers_to_load_to_memoryr"   r2   memory_tensorsr   external_tensormemory_tensorr   r   r   r     s<   #

r   )F)r"   r#   r$   r%   r&   r'   )r"   r#   r;   r<   r&   r=   )r6   r@   r&   r@   )rI   r   rJ   r   rK   r%   rL   r   rM   r   r&   r   )r6   r@   rI   r   r&   r   r}   )
rU   rV   rW   rX   rY   r<   rZ   r[   r&   r=   )
r6   r@   rS   r   r;   r<   rr   r<   r&   rs   )rU   rV   r&   rw   )
rU   rV   r;   r<   rr   r<   rZ   r[   r&   r|   )r   r   r&   r   )r   r   r;   r<   rr   r<   r   r   rZ   r[   r&   r   )(r   
__future__r   typingr   __all__dataclassesloggingrd   collections.abcr
   r   onnx_irr   r   r   r   r+   onnx_ir._polyfillr   _ALIGN_OFFSET_ALIGN_THRESHOLD_ALLOCATION_GRANULARITY	getLoggerr   r   	dataclassr   r	   r:   r   rH   rQ   rT   rq   rv   r   r   r   r   r   r   r   r   <module>   sL   	

&


3

Q!