






"""simple docstring"""







def 						lowercase__()    ->Tuple:




						"""simple docstring"""



						lowercase__    :				Tuple=	[]
						lowercase__    :				int=	1

						while len(A						) < 1e6:
												constant.append(str(A						)						)
												i += 1

						lowercase__    :				List[Any]=	"".join(A						)

						return (
						    int(constant[0]						)
						    * int(constant[9]						)
						    * int(constant[99]						)
						    * int(constant[999]						)
						    * int(constant[9_999]						)
						    * int(constant[99_999]						)
						    * int(constant[999_999]						)
						)


if __name__ == "__main__":
			print(solution())














"""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    __UpperCAmelCase(       nn.Module							):




						"""simple docstring"""




						def __init__(       self      ):
												'''simple docstring'''
												super().__init__()
												lowercase__    :				Any=	nn.Linear(3	,  4      )
												lowercase__    :				Tuple=	nn.BatchNormad(4      )
												lowercase__    :				Dict=	nn.Linear(4	,  5      )




						def 		UpperCAmelCase_	(       self	,  snake_case__      ):
												'''simple docstring'''
												return self.lineara(self.batchnorm(self.lineara(snake_case__      )      )      )


class    __UpperCAmelCase(       SCREAMING_SNAKE_CASE__							):




						"""simple docstring"""




						def 		UpperCAmelCase_	(       self	,  snake_case__	,  *snake_case__	,  **snake_case__      ):
												'''simple docstring'''
												return (args[0] + 1,) + args[1:], kwargs


class    __UpperCAmelCase(       SCREAMING_SNAKE_CASE__							):




						"""simple docstring"""




						def 		UpperCAmelCase_	(       self	,  snake_case__	,  snake_case__      ):
												'''simple docstring'''
												return output + 1


class    __UpperCAmelCase(       unittest.TestCase							):




						"""simple docstring"""




						def 		UpperCAmelCase_	(       self      ):
												'''simple docstring'''
												lowercase__    :				str=	ModelForTest()
												lowercase__    :				str=	ModelHook()

												add_hook_to_module(snake_case__	,  snake_case__      )
												self.assertEqual(test_model._hf_hook	,  snake_case__      )
												self.assertTrue(hasattr(snake_case__	,  "_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(snake_case__      )
												self.assertFalse(hasattr(snake_case__	,  "_hf_hook"      )      )
												self.assertFalse(hasattr(snake_case__	,  "_old_forward"      )      )




						def 		UpperCAmelCase_	(       self      ):
												'''simple docstring'''
												lowercase__    :				int=	ModelForTest()
												lowercase__    :				int=	ModelHook()

												add_hook_to_module(snake_case__	,  snake_case__      )
												add_hook_to_module(snake_case__	,  snake_case__	,  append=snake_case__      )

												self.assertEqual(isinstance(test_model._hf_hook	,  snake_case__      )	,  snake_case__      )
												self.assertEqual(len(test_model._hf_hook.hooks      )	,  2      )
												self.assertTrue(hasattr(snake_case__	,  "_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(snake_case__      )
												self.assertFalse(hasattr(snake_case__	,  "_hf_hook"      )      )
												self.assertFalse(hasattr(snake_case__	,  "_old_forward"      )      )




						def 		UpperCAmelCase_	(       self      ):
												'''simple docstring'''
												lowercase__    :				Dict=	ModelForTest()
												lowercase__    :				int=	torch.randn(2	,  3      )
												lowercase__    :				Optional[Any]=	test_model(x + 1      )
												lowercase__    :				Tuple=	test_model(x + 2      )

												lowercase__    :				str=	PreForwardHook()
												add_hook_to_module(snake_case__	,  snake_case__      )
												lowercase__    :				Tuple=	test_model(snake_case__      )
												self.assertTrue(torch.allclose(snake_case__	,  snake_case__	,  atol=1e-5      )      )

												# Attaching a hook to a model when it already has one replaces, does not chain
												lowercase__    :				Tuple=	PreForwardHook()
												add_hook_to_module(snake_case__	,  snake_case__      )
												lowercase__    :				Optional[Any]=	test_model(snake_case__      )
												self.assertTrue(torch.allclose(snake_case__	,  snake_case__	,  atol=1e-5      )      )

												# You need to use the sequential hook to chain two or more hooks
												lowercase__    :				List[str]=	SequentialHook(PreForwardHook()	,  PreForwardHook()      )
												add_hook_to_module(snake_case__	,  snake_case__      )

												lowercase__    :				Dict=	test_model(snake_case__      )
												assert torch.allclose(snake_case__	,  snake_case__	,  atol=1e-5      )




						def 		UpperCAmelCase_	(       self      ):
												'''simple docstring'''
												lowercase__    :				Tuple=	ModelForTest()
												lowercase__    :				Optional[int]=	torch.randn(2	,  3      )
												lowercase__    :				Optional[int]=	test_model(snake_case__      )

												lowercase__    :				str=	PostForwardHook()
												add_hook_to_module(snake_case__	,  snake_case__      )
												lowercase__    :				Optional[int]=	test_model(snake_case__      )
												self.assertTrue(torch.allclose(snake_case__	,  output + 1	,  atol=1e-5      )      )

												# Attaching a hook to a model when it already has one replaces, does not chain
												lowercase__    :				Tuple=	PostForwardHook()
												add_hook_to_module(snake_case__	,  snake_case__      )
												lowercase__    :				Dict=	test_model(snake_case__      )
												self.assertTrue(torch.allclose(snake_case__	,  output + 1	,  atol=1e-5      )      )

												# You need to use the sequential hook to chain two or more hooks
												lowercase__    :				Optional[Any]=	SequentialHook(PostForwardHook()	,  PostForwardHook()      )
												add_hook_to_module(snake_case__	,  snake_case__      )

												lowercase__    :				List[str]=	test_model(snake_case__      )
												assert torch.allclose(snake_case__	,  output + 2	,  atol=1e-5      )




						def 		UpperCAmelCase_	(       self      ):
												'''simple docstring'''
												lowercase__    :				int=	ModelForTest()
												lowercase__    :				Optional[Any]=	torch.randn(2	,  3      )
												lowercase__    :				int=	test_model(snake_case__      )

												lowercase__    :				Union[str, Any]=	PostForwardHook()
												add_hook_to_module(snake_case__	,  snake_case__      )
												lowercase__    :				Dict=	test_model(snake_case__      )
												self.assertTrue(torch.allclose(snake_case__	,  output + 1      )      )
												self.assertTrue(outputa.requires_grad      )

												lowercase__    :				Any=	True
												lowercase__    :				Optional[int]=	test_model(snake_case__      )
												self.assertFalse(outputa.requires_grad      )




						@require_multi_gpu
						def 		UpperCAmelCase_	(       self      ):
												'''simple docstring'''
												lowercase__    :				Dict=	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
												lowercase__    :				int=	torch.randn(2	,  3      )
												lowercase__    :				List[str]=	model(snake_case__      )
												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(snake_case__	,  AlignDevicesHook(io_same_device=snake_case__      )      )
												lowercase__    :				Tuple=	torch.randn(2	,  3      ).to(0      )
												lowercase__    :				Optional[Any]=	model(snake_case__      )
												self.assertEqual(output.device	,  torch.device(0      )      )




						def 		UpperCAmelCase_	(       self      ):
												'''simple docstring'''
												lowercase__    :				Optional[Any]=	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
												lowercase__    :				Optional[int]=	{"execution_device": 0 if torch.cuda.is_available() else "cpu", "offload": True}

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

												# 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
												lowercase__    :				Optional[int]=	torch.device(hook_kwargs["execution_device"]      )
												self.assertEqual(model.batchnorm.running_mean.device	,  snake_case__      )

												lowercase__    :				List[Any]=	torch.randn(2	,  3      )
												lowercase__    :				str=	model(snake_case__      )
												self.assertEqual(output.device	,  snake_case__      )

												# 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
												lowercase__    :				Optional[int]=	{
												    "execution_device": 0 if torch.cuda.is_available() else "cpu",
												    "offload": True,
												    "offload_buffers": True,
												}

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

												# 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"      )      )

												lowercase__    :				str=	torch.randn(2	,  3      )
												lowercase__    :				str=	model(snake_case__      )
												self.assertEqual(output.device	,  snake_case__      )

												# 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'''
												lowercase__    :				Dict=	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
												lowercase__    :				str=	0 if torch.cuda.is_available() else "cpu"
												attach_align_device_hook(snake_case__	,  execution_device=snake_case__	,  offload=snake_case__      )

												# 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
												lowercase__    :				Dict=	torch.device(snake_case__      )
												self.assertEqual(model.batchnorm.running_mean.device	,  snake_case__      )

												lowercase__    :				Optional[Any]=	torch.randn(2	,  3      )
												lowercase__    :				List[Any]=	model(snake_case__      )
												self.assertEqual(output.device	,  snake_case__      )

												# Removing hooks loads back the weights in the model.
												remove_hook_from_submodules(snake_case__      )
												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(snake_case__	,  execution_device=snake_case__	,  offload=snake_case__	,  offload_buffers=snake_case__      )

												# 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"      )      )

												lowercase__    :				List[str]=	torch.randn(2	,  3      )
												lowercase__    :				List[Any]=	model(snake_case__      )
												self.assertEqual(output.device	,  snake_case__      )

												# Removing hooks loads back the weights in the model.
												remove_hook_from_submodules(snake_case__      )
												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'''
												lowercase__    :				Any=	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
												lowercase__    :				Optional[Any]=	0 if torch.cuda.is_available() else "cpu"
												attach_align_device_hook(
												    snake_case__	,  execution_device=snake_case__	,  offload=snake_case__	,  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
												lowercase__    :				Tuple=	torch.device(snake_case__      )
												self.assertEqual(model.batchnorm.running_mean.device	,  snake_case__      )

												lowercase__    :				str=	torch.randn(2	,  3      )
												lowercase__    :				List[Any]=	model(snake_case__      )
												self.assertEqual(output.device	,  snake_case__      )

												# Removing hooks loads back the weights in the model.
												remove_hook_from_submodules(snake_case__      )
												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(
												    snake_case__	,  execution_device=snake_case__	,  offload=snake_case__	,  weights_map=model.state_dict()	,  offload_buffers=snake_case__	,  )

												# 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"      )      )

												lowercase__    :				Dict=	torch.randn(2	,  3      )
												lowercase__    :				List[str]=	model(snake_case__      )
												self.assertEqual(output.device	,  snake_case__      )

												# Removing hooks loads back the weights in the model.
												remove_hook_from_submodules(snake_case__      )
												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"      )      )






