
"""simple docstring"""

import inspect
import unittest

import torch
import torch.nn as nn

from accelerate.hooks import (
    AlignDevicesHook,
    ModelHook,
    SequentialHook,
    add_hook_to_module,
    attach_align_device_hook,
    remove_hook_from_module,
    remove_hook_from_submodules,
)
from accelerate.test_utils import require_multi_gpu

class __lowerCAmelCase		(				nn.Module      ):





     def __init__(     self				):

      '''simple docstring'''




      super().__init__()
      __UpperCamelCase      =	nn.Linear(3     ,					4				)
      __UpperCamelCase      =	nn.BatchNormad(4				)
      __UpperCamelCase      =	nn.Linear(4     ,					5				)







     def 						UpperCAmelCase (     self     ,					__UpperCAmelCase				):

      '''simple docstring'''




      return self.lineara(self.batchnorm(self.lineara(__UpperCAmelCase				)				)				)


class __lowerCAmelCase		(				__SCREAMING_SNAKE_CASE      ):





     def 						UpperCAmelCase (     self     ,					__UpperCAmelCase     ,					*__UpperCAmelCase     ,					**__UpperCAmelCase				):

      '''simple docstring'''




      return (args[0] + 1,) + args[1:], kwargs


class __lowerCAmelCase		(				__SCREAMING_SNAKE_CASE      ):





     def 						UpperCAmelCase (     self     ,					__UpperCAmelCase     ,					__UpperCAmelCase				):

      '''simple docstring'''




      return output + 1


class __lowerCAmelCase		(				unittest.TestCase      ):





     def 						UpperCAmelCase (     self				):

      '''simple docstring'''




      __UpperCamelCase      =	ModelForTest()
      __UpperCamelCase      =	ModelHook()

      add_hook_to_module(__UpperCAmelCase     ,					__UpperCAmelCase				)
      self.assertEqual(test_model._hf_hook     ,					__UpperCAmelCase				)
      self.assertTrue(hasattr(__UpperCAmelCase     ,					'_old_forward'				)				)

      # Check adding the hook did not change the name or the signature
      self.assertEqual(test_model.forward.__name__     ,					'forward'				)
      self.assertListEqual(list(inspect.signature(test_model.forward				).parameters				)     ,					['x']				)

      remove_hook_from_module(__UpperCAmelCase				)
      self.assertFalse(hasattr(__UpperCAmelCase     ,					'_hf_hook'				)				)
      self.assertFalse(hasattr(__UpperCAmelCase     ,					'_old_forward'				)				)





     def 						UpperCAmelCase (     self				):

      '''simple docstring'''




      __UpperCamelCase      =	ModelForTest()
      __UpperCamelCase      =	ModelHook()

      add_hook_to_module(__UpperCAmelCase     ,					__UpperCAmelCase				)
      add_hook_to_module(__UpperCAmelCase     ,					__UpperCAmelCase     ,					append=__UpperCAmelCase				)

      self.assertEqual(isinstance(test_model._hf_hook     ,					__UpperCAmelCase				)     ,					__UpperCAmelCase				)
      self.assertEqual(len(test_model._hf_hook.hooks				)     ,					2				)
      self.assertTrue(hasattr(__UpperCAmelCase     ,					'_old_forward'				)				)

      # Check adding the hook did not change the name or the signature
      self.assertEqual(test_model.forward.__name__     ,					'forward'				)
      self.assertListEqual(list(inspect.signature(test_model.forward				).parameters				)     ,					['x']				)

      remove_hook_from_module(__UpperCAmelCase				)
      self.assertFalse(hasattr(__UpperCAmelCase     ,					'_hf_hook'				)				)
      self.assertFalse(hasattr(__UpperCAmelCase     ,					'_old_forward'				)				)





     def 						UpperCAmelCase (     self				):

      '''simple docstring'''




      __UpperCamelCase      =	ModelForTest()
      __UpperCamelCase      =	torch.randn(2     ,					3				)
      __UpperCamelCase      =	test_model(x + 1				)
      __UpperCamelCase      =	test_model(x + 2				)

      __UpperCamelCase      =	PreForwardHook()
      add_hook_to_module(__UpperCAmelCase     ,					__UpperCAmelCase				)
      __UpperCamelCase      =	test_model(__UpperCAmelCase				)
      self.assertTrue(torch.allclose(__UpperCAmelCase     ,					__UpperCAmelCase     ,					atol=1E-5				)				)

      # Attaching a hook to a model when it already has one replaces, does not chain
      __UpperCamelCase      =	PreForwardHook()
      add_hook_to_module(__UpperCAmelCase     ,					__UpperCAmelCase				)
      __UpperCamelCase      =	test_model(__UpperCAmelCase				)
      self.assertTrue(torch.allclose(__UpperCAmelCase     ,					__UpperCAmelCase     ,					atol=1E-5				)				)

      # You need to use the sequential hook to chain two or more hooks
      __UpperCamelCase      =	SequentialHook(PreForwardHook()     ,					PreForwardHook()				)
      add_hook_to_module(__UpperCAmelCase     ,					__UpperCAmelCase				)

      __UpperCamelCase      =	test_model(__UpperCAmelCase				)
      assert torch.allclose(__UpperCAmelCase     ,					__UpperCAmelCase     ,					atol=1E-5				)





     def 						UpperCAmelCase (     self				):

      '''simple docstring'''




      __UpperCamelCase      =	ModelForTest()
      __UpperCamelCase      =	torch.randn(2     ,					3				)
      __UpperCamelCase      =	test_model(__UpperCAmelCase				)

      __UpperCamelCase      =	PostForwardHook()
      add_hook_to_module(__UpperCAmelCase     ,					__UpperCAmelCase				)
      __UpperCamelCase      =	test_model(__UpperCAmelCase				)
      self.assertTrue(torch.allclose(__UpperCAmelCase     ,					output + 1     ,					atol=1E-5				)				)

      # Attaching a hook to a model when it already has one replaces, does not chain
      __UpperCamelCase      =	PostForwardHook()
      add_hook_to_module(__UpperCAmelCase     ,					__UpperCAmelCase				)
      __UpperCamelCase      =	test_model(__UpperCAmelCase				)
      self.assertTrue(torch.allclose(__UpperCAmelCase     ,					output + 1     ,					atol=1E-5				)				)

      # You need to use the sequential hook to chain two or more hooks
      __UpperCamelCase      =	SequentialHook(PostForwardHook()     ,					PostForwardHook()				)
      add_hook_to_module(__UpperCAmelCase     ,					__UpperCAmelCase				)

      __UpperCamelCase      =	test_model(__UpperCAmelCase				)
      assert torch.allclose(__UpperCAmelCase     ,					output + 2     ,					atol=1E-5				)





     def 						UpperCAmelCase (     self				):

      '''simple docstring'''




      __UpperCamelCase      =	ModelForTest()
      __UpperCamelCase      =	torch.randn(2     ,					3				)
      __UpperCamelCase      =	test_model(__UpperCAmelCase				)

      __UpperCamelCase      =	PostForwardHook()
      add_hook_to_module(__UpperCAmelCase     ,					__UpperCAmelCase				)
      __UpperCamelCase      =	test_model(__UpperCAmelCase				)
      self.assertTrue(torch.allclose(__UpperCAmelCase     ,					output + 1				)				)
      self.assertTrue(outputa.requires_grad				)

      __UpperCamelCase      =	True
      __UpperCamelCase      =	test_model(__UpperCAmelCase				)
      self.assertFalse(outputa.requires_grad				)





     @require_multi_gpu
     def 						UpperCAmelCase (     self				):

      '''simple docstring'''




      __UpperCamelCase      =	ModelForTest()
      # Everything is on CPU
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.batchnorm.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)

      # This will move each submodule on different devices
      add_hook_to_module(model.lineara     ,					AlignDevicesHook(execution_device=0				)				)
      add_hook_to_module(model.batchnorm     ,					AlignDevicesHook(execution_device=0				)				)
      add_hook_to_module(model.lineara     ,					AlignDevicesHook(execution_device=1				)				)

      self.assertEqual(model.lineara.weight.device     ,					torch.device(0				)				)
      self.assertEqual(model.batchnorm.weight.device     ,					torch.device(0				)				)
      self.assertEqual(model.batchnorm.running_mean.device     ,					torch.device(0				)				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device(1				)				)

      # We can still make a forward pass. The input does not need to be on any particular device
      __UpperCamelCase      =	torch.randn(2     ,					3				)
      __UpperCamelCase      =	model(__UpperCAmelCase				)
      self.assertEqual(output.device     ,					torch.device(1				)				)

      # We can add a general hook to put back output on same device as input.
      add_hook_to_module(__UpperCAmelCase     ,					AlignDevicesHook(io_same_device=__UpperCAmelCase				)				)
      __UpperCamelCase      =	torch.randn(2     ,					3				).to(0				)
      __UpperCamelCase      =	model(__UpperCAmelCase				)
      self.assertEqual(output.device     ,					torch.device(0				)				)





     def 						UpperCAmelCase (     self				):

      '''simple docstring'''




      __UpperCamelCase      =	ModelForTest()

      # Everything is on CPU
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.batchnorm.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)

      # This will move each submodule on different devices
      __UpperCamelCase      =	{'execution_device': 0 if torch.cuda.is_available() else 'cpu', 'offload': True}

      add_hook_to_module(model.lineara     ,					AlignDevicesHook(**__UpperCAmelCase				)				)
      add_hook_to_module(model.batchnorm     ,					AlignDevicesHook(**__UpperCAmelCase				)				)
      add_hook_to_module(model.lineara     ,					AlignDevicesHook(**__UpperCAmelCase				)				)

      # Parameters have been offloaded, so on the meta device
      self.assertEqual(model.lineara.weight.device     ,					torch.device('meta'				)				)
      self.assertEqual(model.batchnorm.weight.device     ,					torch.device('meta'				)				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('meta'				)				)
      # Buffers are not included in the offload by default, so are on the execution device
      __UpperCamelCase      =	torch.device(hook_kwargs['execution_device']				)
      self.assertEqual(model.batchnorm.running_mean.device     ,					__UpperCAmelCase				)

      __UpperCamelCase      =	torch.randn(2     ,					3				)
      __UpperCamelCase      =	model(__UpperCAmelCase				)
      self.assertEqual(output.device     ,					__UpperCAmelCase				)

      # Removing hooks loads back the weights in the model.
      remove_hook_from_module(model.lineara				)
      remove_hook_from_module(model.batchnorm				)
      remove_hook_from_module(model.lineara				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.batchnorm.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)

      # Now test with buffers included in the offload
      __UpperCamelCase      =	{
          'execution_device': 0 if torch.cuda.is_available() else 'cpu',
          'offload': True,
          'offload_buffers': True,
      }

      add_hook_to_module(model.lineara     ,					AlignDevicesHook(**__UpperCAmelCase				)				)
      add_hook_to_module(model.batchnorm     ,					AlignDevicesHook(**__UpperCAmelCase				)				)
      add_hook_to_module(model.lineara     ,					AlignDevicesHook(**__UpperCAmelCase				)				)

      # Parameters have been offloaded, so on the meta device, buffers included
      self.assertEqual(model.lineara.weight.device     ,					torch.device('meta'				)				)
      self.assertEqual(model.batchnorm.weight.device     ,					torch.device('meta'				)				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('meta'				)				)
      self.assertEqual(model.batchnorm.running_mean.device     ,					torch.device('meta'				)				)

      __UpperCamelCase      =	torch.randn(2     ,					3				)
      __UpperCamelCase      =	model(__UpperCAmelCase				)
      self.assertEqual(output.device     ,					__UpperCAmelCase				)

      # Removing hooks loads back the weights in the model.
      remove_hook_from_module(model.lineara				)
      remove_hook_from_module(model.batchnorm				)
      remove_hook_from_module(model.lineara				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.batchnorm.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)





     def 						UpperCAmelCase (     self				):

      '''simple docstring'''




      __UpperCamelCase      =	ModelForTest()

      # Everything is on CPU
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.batchnorm.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)

      # This will move each submodule on different devices
      __UpperCamelCase      =	0 if torch.cuda.is_available() else 'cpu'
      attach_align_device_hook(__UpperCAmelCase     ,					execution_device=__UpperCAmelCase     ,					offload=__UpperCAmelCase				)

      # Parameters have been offloaded, so on the meta device
      self.assertEqual(model.lineara.weight.device     ,					torch.device('meta'				)				)
      self.assertEqual(model.batchnorm.weight.device     ,					torch.device('meta'				)				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('meta'				)				)
      # Buffers are not included in the offload by default, so are on the execution device
      __UpperCamelCase      =	torch.device(__UpperCAmelCase				)
      self.assertEqual(model.batchnorm.running_mean.device     ,					__UpperCAmelCase				)

      __UpperCamelCase      =	torch.randn(2     ,					3				)
      __UpperCamelCase      =	model(__UpperCAmelCase				)
      self.assertEqual(output.device     ,					__UpperCAmelCase				)

      # Removing hooks loads back the weights in the model.
      remove_hook_from_submodules(__UpperCAmelCase				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.batchnorm.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)

      # Now test with buffers included in the offload
      attach_align_device_hook(__UpperCAmelCase     ,					execution_device=__UpperCAmelCase     ,					offload=__UpperCAmelCase     ,					offload_buffers=__UpperCAmelCase				)

      # Parameters have been offloaded, so on the meta device, buffers included
      self.assertEqual(model.lineara.weight.device     ,					torch.device('meta'				)				)
      self.assertEqual(model.batchnorm.weight.device     ,					torch.device('meta'				)				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('meta'				)				)
      self.assertEqual(model.batchnorm.running_mean.device     ,					torch.device('meta'				)				)

      __UpperCamelCase      =	torch.randn(2     ,					3				)
      __UpperCamelCase      =	model(__UpperCAmelCase				)
      self.assertEqual(output.device     ,					__UpperCAmelCase				)

      # Removing hooks loads back the weights in the model.
      remove_hook_from_submodules(__UpperCAmelCase				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.batchnorm.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)







     def 						UpperCAmelCase (     self				):

      '''simple docstring'''




      __UpperCamelCase      =	ModelForTest()

      # Everything is on CPU
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.batchnorm.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)

      # This will move each submodule on different devices
      __UpperCamelCase      =	0 if torch.cuda.is_available() else 'cpu'
      attach_align_device_hook(
          __UpperCAmelCase     ,					execution_device=__UpperCAmelCase     ,					offload=__UpperCAmelCase     ,					weights_map=model.state_dict()				)

      # Parameters have been offloaded, so on the meta device
      self.assertEqual(model.lineara.weight.device     ,					torch.device('meta'				)				)
      self.assertEqual(model.batchnorm.weight.device     ,					torch.device('meta'				)				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('meta'				)				)
      # Buffers are not included in the offload by default, so are on the execution device
      __UpperCamelCase      =	torch.device(__UpperCAmelCase				)
      self.assertEqual(model.batchnorm.running_mean.device     ,					__UpperCAmelCase				)

      __UpperCamelCase      =	torch.randn(2     ,					3				)
      __UpperCamelCase      =	model(__UpperCAmelCase				)
      self.assertEqual(output.device     ,					__UpperCAmelCase				)

      # Removing hooks loads back the weights in the model.
      remove_hook_from_submodules(__UpperCAmelCase				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.batchnorm.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)

      # Now test with buffers included in the offload
      attach_align_device_hook(
          __UpperCAmelCase     ,					execution_device=__UpperCAmelCase     ,					offload=__UpperCAmelCase     ,					weights_map=model.state_dict()     ,					offload_buffers=__UpperCAmelCase     ,					)

      # Parameters have been offloaded, so on the meta device, buffers included
      self.assertEqual(model.lineara.weight.device     ,					torch.device('meta'				)				)
      self.assertEqual(model.batchnorm.weight.device     ,					torch.device('meta'				)				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('meta'				)				)
      self.assertEqual(model.batchnorm.running_mean.device     ,					torch.device('meta'				)				)

      __UpperCamelCase      =	torch.randn(2     ,					3				)
      __UpperCamelCase      =	model(__UpperCAmelCase				)
      self.assertEqual(output.device     ,					__UpperCAmelCase				)

      # Removing hooks loads back the weights in the model.
      remove_hook_from_submodules(__UpperCAmelCase				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.batchnorm.weight.device     ,					torch.device('cpu'				)				)
      self.assertEqual(model.lineara.weight.device     ,					torch.device('cpu'				)				)





"""simple docstring"""

from __future__ import annotations

from typing import Any






def 							A						(    snake_case				:list		)				->     int:
 if not postfix_notation:
  return 0

 __UpperCamelCase      =	{'+', '-', '*', '/'}
 __UpperCamelCase      =	[]

 for token in postfix_notation:
  if token in operations:
   __UpperCamelCase  ,     __UpperCamelCase      =	stack.pop(), stack.pop()
   if token == "+":
    stack.append(a + b		)
   elif token == "-":
    stack.append(a - b		)
   elif token == "*":
    stack.append(a * b		)
   else:
    if a * b < 0 and a % b != 0:
     stack.append(a // b + 1		)
    else:
     stack.append(a // b		)
  else:
   stack.append(int(snake_case		)		)

 return stack.pop()


if __name__ == "__main__":
      import doctest

      doctest.testmod()



