большая разница между точностью модели pytorch, использующей процессор и графический процессор для обучения

#python #pytorch #gpu #cpu

Вопрос:

Я обучил ту же модель PyTorch в системе ubuntu с графическим процессором tesla k80, и я получил точность около 32%, но когда я запускаю ее с использованием процессора, точность составляет 43%. также установлены Cuda-инструментарий и библиотека cudnn. nvidia-драйвер: 470.63.01

версия nvcc: 10.1

каковы возможные причины такой большой разницы?

Для более подробной информации я использовал этот код https://github.com/copenlu/xformer-multi-source-domain-adaptation и адаптировал это для моей проблемы с ответом на вопрос, класс модели:

 class MultiViewTransformerNetworkAveragingIndividuals(nn.Module):
   
    Multi-view transformer network for domain adaptation
   

    def __init__(self, bert_model, bert_config, n_domains: int = 2, n_classes: int = 2):
        super(MultiViewTransformerNetworkAveragingIndividuals, self).__init__()
        
        self.domain_experts = nn.ModuleList([AutoModelForQuestionAnswering.from_pretrained(bert_model,config=bert_config) for _ in range(n_domains)])
        self.shared_bert = AutoModelForQuestionAnswering.from_pretrained(bert_model,config=bert_config)

        self.n_domains = n_domains
        self.n_classes = n_classes

        # Default weight is averaging
        self.weights = [1. / (self.n_domains   1)] * (self.n_domains   1)

        self.average = False

    def forward(
            self,
            input_ids: torch.LongTensor,
            attention_mask: torch.LongTensor,
            head_mask=None,
            inputs_embeds=None,
            start_positions=None,
            end_positions=None,
            output_attentions=None,
            output_hidden_states=None,
            return_dict=None,
            domains: torch.LongTensor = None,
            return_logits: bool = False
    ):
        
        outputs = self.shared_bert(input_ids, attention_mask,head_mask=head_mask,inputs_embeds=inputs_embeds,output_attentions=output_attentions,
            output_hidden_states=output_hidden_states,return_dict=return_dict)
        logits_shared_start = outputs[0]
        logits_shared_end = outputs[1]
        
        softmax = nn.Softmax()

        if not self.average:
            if domains is not None:   
                logits = self.domain_experts[domains[0]](input_ids, attention_mask,head_mask=head_mask,inputs_embeds=inputs_embeds,output_attentions=output_attentions,
            output_hidden_states=output_hidden_states,return_dict=return_dict)
                logits_start=logits[0]
                logits_end=logits[1]
                # b x n_dom( 1) x nclasses
                start_preds = softmax(logits_start)
                end_preds = softmax(logits_end)
            else:
                
                logits_start = logits_shared_start
                logits_end = logits_shared_end
                # b x n_dom( 1) x nclasses
                start_preds = softmax(logits_start)
                end_preds = softmax(logits_end)
                
        else:
            logits_private = [self.domain_experts[d](input_ids, attention_mask,head_mask=head_mask,inputs_embeds=inputs_embeds,output_attentions=output_attentions,
            output_hidden_states=output_hidden_states,return_dict=return_dict) for d in
                              range(self.n_domains)]
            logits_private_start=[log_private[0] for log_private in logits_private]
            logits_private_end=[log_private[1] for log_private in logits_private]
            logits_start = logits_private_start   [logits_shared_start]
            logits_end = logits_private_end   [logits_shared_end]
            if return_logits:
                return (logits_start,logits_end)
            attn = torch.FloatTensor(self.weights).view(1, -1, 1) 
           
            # b x n_dom( 1) x nclasses
            start_preds = torch.stack([softmax(logs) for logs in logits_start], dim=1)
            end_preds = torch.stack([softmax(logs) for logs in logits_end], dim=1)
            # Apply attention
            start_preds = torch.sum(start_preds * attn, dim=1)
            end_preds = torch.sum(end_preds * attn, dim=1)
        
        
        outputs = (start_preds,end_preds,)
        loss=None
        if start_positions is not None and end_positions is not None:
            if len(start_positions.size()) > 1:
                start_positions = start_positions.squeeze(-1)
            if len(end_positions.size()) > 1:
                end_positions = end_positions.squeeze(-1)
            # sometimes the start/end positions are outside our model inputs, we ignore these terms
            ignored_index = start_preds.size(1)
            start_positions.clamp_(0, ignored_index)
            end_positions.clamp_(0, ignored_index)
            
            # LogSoftmax   NLLLoss
            loss_fn = nn.NLLLoss()
            xent = nn.CrossEntropyLoss()
            s_loss =  loss_fn(torch.log(start_preds), start_positions)
            e_loss =  loss_fn(torch.log(end_preds), end_positions)
            loss_s=(s_loss e_loss/2)
            loss=loss_s
            s_loss_t=xent(logits_shared_start, start_positions)
            e_loss_t=xent(logits_shared_end, end_positions)
            loss_t=(s_loss_t e_loss_t)/2
            loss =loss_t
            # Strong supervision on in domain
            #if domains is not None:
            
        return QuestionAnsweringModelOutput(
            loss=loss,
            start_logits=start_preds,
            end_logits=end_preds,
        )
        
 

когда я запускаю этот код шаг за шагом, выходные данные модели (start_logits, end_logits и потери) отличаются от процессора к графическому процессору.

следует отметить, что семена инициализируются в первой из программ как:

 # Set all the seeds
    seed = args.seed
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)
    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = False
 

и результаты не меняются при многократных запусках.

Комментарии:

1. невозможно ответить без подробностей контекста, таких как архитектура модели, набор данных, обучающий конвейер и т.д.

2. Я отредактировал это, чтобы включить более подробную информацию

3. На это нетрудно ответить, так как мы знаем, что op использует cudnn, что уже создает проблему воспроизводимости.

4. У меня нет проблем с воспроизводимостью, потому что при запуске программы с процессором всегда получается точность 43%, а при запуске программы с графическим процессором всегда получается 32%. проблема в этой разнице между процессором и графическим процессором

Ответ №1:

Согласно странице документации Nvidia CUDNN:

  1. Воспроизводимость (детерминизм) По замыслу большинство подпрограмм cuDNN из данной версии генерируют одинаковые битовые результаты при выполнении на графических процессорах с одинаковой архитектурой и одинаковым количеством SMS. Однако битовая воспроизводимость не гарантируется в разных версиях, так как реализация данной процедуры может измениться. В текущем выпуске следующие процедуры не гарантируют воспроизводимость, поскольку они используют атомарные операции:
    • cudnnConvolutionBackwardFilter когда CUDNN_CONVOLUTION_BWD_FILTER_ALGO_0 или CUDNN_CONVOLUTION_BWD_FILTER_ALGO_3 используется
    • cudnnConvolutionBackwardData когда CUDNN_CONVOLUTION_BWD_DATA_ALGO_0 используется
    • cudnnPoolingBackward когда CUDNN_POOLING_MAX используется
    • cudnnSpatialTfSamplerBackward
    • cudnnCTCLoss и cudnnCTCLoss_v8 когда CUDNN_CTC_LOSS_ALGO_NON_DETERMINSTIC используется

Таким образом, даже несмотря на то, что вы используете deterministic = true cudnn, некоторые операции не являются детерминированными.

Попробуйте отключить cudnn и посмотрите, не устранена ли проблема.

Комментарии:

1. Я добавил это: «torch.backends.cudnn.enabled=False», но результаты не изменились