o
    pi                     @   s   d dl Z d dlZddlmZmZ ddlmZ ddlmZ	 ddlm
Z dd Zd	d
 Zdd Zdd ZdddZdddZdd Zdd ZG dd dejjZG dd dejjZdS )    N   )BaseMetricLossFunctionCrossBatchMemory)	BaseMiner)common_functions)loss_and_miner_utilsc                   C   s   t j o	t j S N)torchdistributedis_availableis_initialized r   r   ]/home/ubuntu/.local/lib/python3.10/site-packages/pytorch_metric_learning/utils/distributed.pyis_distributed   s   r   c                    s`   t j }|dkr.t j } fddt|D }t j|   || t j|ddS d S )N   c                    s   g | ]}t  qS r   )r	   	ones_like).0_xr   r   
<listcomp>   s    zall_gather.<locals>.<listcomp>r   dim)	r	   r
   get_world_sizeget_rankrange
all_gather
contiguouspopcat)r   
world_sizerankx_listr   r   r   r      s   


r   c                 C   s.   t  sdS t| }|d urt|nd }||fS NNN)r   r   )emblabelsref_emb
ref_labelsr   r   r    all_gather_embeddings_and_labels   s
   r)   c                 C   sd   | j }|d urtj||d}t| |\}}tj| |gdd}|d ur+tj||gddnd }|||fS Ndevicer   r   )r,   c_f	to_devicer)   r	   r   )r%   r&   r,   dist_embdist_labelsall_emb
all_labelsr   r   r   gather'   s   
r3   c           	      C   s>   t | |\}}}d\}}|d urt ||\}}}|||||fS r#   )r3   )	r%   r&   r'   r(   r1   r2   all_ref_emball_ref_labelsr   r   r   r   gather_emb_and_ref3   s
   r6   c                 C   sJ   | j }tjt| |d}|r||| ||}nt| |}t||t|S )Nr+   )r,   r	   arangelenlmuget_all_pairs_indicesremove_self_comparisons)r&   r(   
embeddingsr'   minerr,   curr_batch_idxindices_tupler   r   r   get_indices_tuple=   s   r@   c                 C   s0   | d u r| S t j| |d} tj| t| gddS r*   )r-   r.   r	   r   r   )enqueue_maskr,   r   r   r   gather_enqueue_maskG   s   rB   c                 C   s   |d u r| S |S r   r   )regularrefr   r   r   select_ref_or_regularN   s   rE   c                       sB   e Zd Zd fdd	Z					dddZdd Zd	d
 Z  ZS )DistributedLossWrapperFc                    sF   t    t|ttfstdt|tr|rtd|| _|| _d S )NzEThe input loss must extend BaseMetricLossFunction or CrossBatchMemoryz?CrossBatchMemory with efficient=True is not currently supported)	super__init__
isinstancer   r   	TypeError
ValueErrorloss	efficient)selfrL   rM   	__class__r   r   rH   S   s   

zDistributedLossWrapper.__init__Nc           	      C   sf   t  std | |||||S tj }||||||g}t| jtr.| j	g ||R  S | j
| S )Nz\DistributedLossWrapper is being used in a non-distributed setting. Returning the loss as is.)r   warningswarnrL   r	   r
   r   rI   r   forward_cross_batchforward_regular_loss)	rN   r<   r&   r?   r'   r(   rA   r    common_argsr   r   r   forward`   s    	

zDistributedLossWrapper.forwardc                 C   s   |dkr|  |||||S t||||\}}}	}
}| jr@|d ur%t||
}t||	}|d u r3t||}|  |||||}|| S |  ||||	|
}|| S Nr   )rL   r6   rM   rE   r@   )rN   r%   r&   r?   r'   r(   r    r1   r2   r4   r5   rL   r   r   r   rT   |   s"   



z+DistributedLossWrapper.forward_regular_lossc                 C   sl   |d us|d urt d|dkr| ||||S t||||\}}	}
}
}
t||j}| ||	||}|| S )Nz>CrossBatchMemory is not compatible with ref_emb and ref_labelsr   )rK   rL   r6   rB   r,   )rN   r%   r&   r?   r'   r(   r    rA   r1   r2   r   rL   r   r   r   rS      s   
z*DistributedLossWrapper.forward_cross_batchF)NNNNN)__name__
__module____qualname__rH   rV   rT   rS   __classcell__r   r   rO   r   rF   R   s    
rF   c                       s(   e Zd Zd fdd	ZdddZ  ZS )	DistributedMinerWrapperFc                    s,   t    t|tstd|| _|| _d S )Nz%The input miner must extend BaseMiner)rG   rH   rI   r   rJ   r=   rM   )rN   r=   rM   rO   r   r   rH      s
   


z DistributedMinerWrapper.__init__Nc           
      C   sv   t j }|dkr| ||||S t||||\}}}}	}| jr3t||	}t||}t||||| jS | ||||	S rW   )r	   r
   r   r=   r6   rM   rE   r@   )
rN   r%   r&   r'   r(   r    r1   r2   r4   r5   r   r   r   rV      s   


zDistributedMinerWrapper.forwardrX   r$   )rY   rZ   r[   rH   rV   r\   r   r   rO   r   r]      s    r]   r$   )NNN)rQ   r	   lossesr   r   minersr   utilsr   r-   r   r9   r   r   r)   r3   r6   r@   rB   rE   nnModulerF   r]   r   r   r   r   <module>   s     	



\