o
    i/$                     @   s   d dl Z d dlZd dlZd dlZd dlZd dlmZmZm	Z	 d dl
mZmZmZ dd ZG dd de	jZG dd	 d	e	jjZG d
d deZdS )    N)Variablecudatraining)gather_gradsgather_paramsscatter_gradsc              	   C   s   t t}| D ].}t|}|dur&| }||}|t|  |7  < W d   n1 s0w   Y  qtdd t	
|D S )zCalculate the norm of the array.

    Args:
        arr (numpy.ndarray)

    Returns:
        Float: Sum of the norm calculated from the given array.

    Nc                 S   s   g | ]}t |qS  )float).0ir   r   \/home/ubuntu/.local/lib/python3.10/site-packages/espnet/nets/chainer_backend/rnn/training.py
<listcomp>'   s    zsum_sqnorm.<locals>.<listcomp>)collectionsdefaultdictr	   r   get_device_from_arrayraveldotintsumsix
itervalues)arrsq_sumxdevsr   r   r   
sum_sqnorm   s   


r   c                       2   e Zd ZdZd	 fdd	Zdd Zdd Z  ZS )
CustomUpdatera%  Custom updater for chainer.

    Args:
        train_iter (iterator | dict[str, iterator]): Dataset iterator for the
            training dataset. It can also be a dictionary that maps strings to
            iterators. If this is just an iterator, then the iterator is
            registered by the name ``'main'``.
        optimizer (optimizer | dict[str, optimizer]): Optimizer to update
            parameters. It can also be a dictionary that maps strings to
            optimizers. If this is just an optimizer, then the optimizer is
            registered by the name ``'main'``.
        converter (espnet.asr.chainer_backend.asr.CustomConverter): Converter
            function to build input arrays. Each batch extracted by the main
            iterator and the ``device`` option are passed to this function.
            :func:`chainer.dataset.concat_examples` is used by default.
        device (int or dict): The destination device info to send variables. In the
            case of cpu or single gpu, `device=-1 or 0`, respectively.
            In the case of multi-gpu, `device={"main":0, "sub_1": 1, ...}`.
        accum_grad (int):The number of gradient accumulation. if set to 2, the network
            parameters will be updated once in twice,
            i.e. actual batchsize will be doubled.

       c                    s4   t t| j||||d d| _|| _d| _|| _d S )N)	converterdevicer   T)superr   __init__forward_count
accum_gradstartr!   )self
train_iter	optimizerr    r!   r%   	__class__r   r   r#   C   s   

zCustomUpdater.__init__c                 C   s   |  d}| d}| }| || j}| jr |j  d| _|j| | j }|	  |
  |  jd7  _| j| jkr?dS d| _ttdd |jdD }td| t|retd	 n|  |j  dS )
z'Main update routine for Custom Updater.mainFr   Nr   c                 S      g | ]}|j qS r   gradr
   pr   r   r   r   f       z-CustomUpdater.update_core.<locals>.<listcomp>grad norm={}&grad norm is nan. Do not update model.)get_iteratorget_optimizernextr    r!   r&   target
cleargradsr%   backwardunchain_backwardr$   npsqrtr   paramslogginginfoformatmathisnanwarningupdate)r'   r(   r)   batchr   loss	grad_normr   r   r   update_coreN   s,   



zCustomUpdater.update_corec                 C   (   |    | jdkr|  jd7  _d S d S Nr   r   rI   r$   	iterationr'   r   r   r   rE   o      
zCustomUpdater.updater   __name__
__module____qualname____doc__r#   rI   rE   __classcell__r   r   r*   r   r   *   s
    !r   c                       r   )
CustomParallelUpdatera  Custom Parallel Updater for chainer.

    Defines the main update routine.

    Args:
        train_iter (iterator | dict[str, iterator]): Dataset iterator for the
            training dataset. It can also be a dictionary that maps strings to
            iterators. If this is just an iterator, then the iterator is
            registered by the name ``'main'``.
        optimizer (optimizer | dict[str, optimizer]): Optimizer to update
            parameters. It can also be a dictionary that maps strings to
            optimizers. If this is just an optimizer, then the optimizer is
            registered by the name ``'main'``.
        converter (espnet.asr.chainer_backend.asr.CustomConverter): Converter
            function to build input arrays. Each batch extracted by the main
            iterator and the ``device`` option are passed to this function.
            :func:`chainer.dataset.concat_examples` is used by default.
        device (torch.device): Device to which the training data is sent.
            Negative value
            indicates the host memory (CPU).
        accum_grad (int):The number of gradient accumulation. if set to 2,
            the network parameters will be updated once in twice,
            i.e. actual batchsize will be doubled.

    r   c                    s:   t t| j||||d ddlm} || _d| _|| _d S )N)r    devicesr   )nccl)r"   rW   r#   	cupy.cudarY   r%   r$   )r'   train_itersr)   r    rX   r%   rY   r*   r   r   r#      s   

zCustomParallelUpdater.__init__c           	   
   C   s  |    | d t| jd  | d}| d }| || jd }| j	| | j
 }|  |  tjj}| jdurbt| j	}| j|jj|jj|j| jj| jjd|j t| j	| ~|  jd7  _| j| j
krx	 W d   dS d| _ttdd |jdD }t d	!| t"#|rt$d
 n|%  | j	&  | jdurt'| j	}| j(|jj|j| jjd|j W d   dS W d   dS 1 sw   Y  dS )z3Main Update routine of the custom parallel updater.)rE   Nr   r,   Nr   c                 S   r-   r   r.   r0   r   r   r   r      r2   z5CustomParallelUpdater.update_core.<locals>.<listcomp>Fr3   r4   ))setup_workers_send_messager   Device_devicesr6   r5   r7   r    _masterr%   r:   r;   Streamnullcommr   reducedataptrsizerY   
NCCL_FLOATNCCL_SUMr   r$   r<   r=   r   r8   r>   r?   r@   rA   rB   rC   rD   rE   r9   r   bcast)	r'   r)   rF   r   rG   null_streamggrH   gpr   r   r   rI      sX   



	



-"z!CustomParallelUpdater.update_corec                 C   rJ   rK   rL   rN   r   r   r   rE      rO   zCustomParallelUpdater.updaterP   rQ   r   r   r*   r   rW   u   s
    8rW   c                   @   s"   e Zd ZdZdddZdd ZdS )	CustomConverterz\Custom Converter.

    Args:
        subsampling_factor (int): The subsampling factor.

    r   c                 C   s
   || _ d S Nsubsampling_factor)r'   rq   r   r   r   r#      s   
zCustomConverter.__init__c                    s   |dkrt jntt|dksJ |d \}} jdkr% fdd|D }dd |D }fdd|D }j|jd}fd	d|D }|||fS )
ai  Perform sabsampling.

        Args:
            batch (list): Batch that will be sabsampled.
            device (device): GPU device.

        Returns:
            chainer.Variable: xp.array that sabsampled from batch.
            xp.array: xp.array of the length of the mini-batches.
            chainer.Variable: xp.array that sabsampled from batch.

        r   r   c                    s$   g | ]}|d d  j d d f qS ro   rp   r
   r   rN   r   r   r      s   $ z,CustomConverter.__call__.<locals>.<listcomp>c                 S   s   g | ]}|j d  qS )r   )shapers   r   r   r   r      s    c                        g | ]}t  j| jd qS dtype)r   arrayfloat32rs   xpr   r   r           rw   c                    ru   rv   )r   ry   int32)r
   yr{   r   r   r     r}   )r   cupyr<   lenrq   ry   r~   )r'   rF   r!   xsysilensr   )r'   r|   r   __call__   s   

zCustomConverter.__call__NrP   )rR   rS   rT   rU   r#   r   r   r   r   r   rn      s    
rn   )r   r?   rB   numpyr<   r   chainerr   r   r   7chainer.training.updaters.multiprocess_parallel_updaterr   r   r   r   StandardUpdaterr   updatersMultiprocessParallelUpdaterrW   objectrn   r   r   r   r   <module>   s   Kd