
import gc
import threading
import time

import psutil
import torch







class        lowercase	:




							def __init__(       self):
												lowercase					=		psutil.Process()
												lowercase					=		False




							def 				A__   (       self):
												lowercase					=		-1

												while True:
																	lowercase					=		max(self.process.memory_info().rss     ,self.cpu_memory_peak)

																	# can't sleep or will not catch the peak right (this comment is here on purpose)
																	if not self.peak_monitoring:
																						break




							def 				A__   (       self):
												lowercase					=		True
												lowercase					=		threading.Thread(target=self.peak_monitor)
												lowercase					=		True
												self.thread.start()





							def 				A__   (       self):
												lowercase					=		False
												self.thread.join()
												return self.cpu_memory_peak


lowercase__	:List[Any]										=					PeakCPUMemory()



def  UpperCamelCase					(							):
					'''simple docstring'''
					# Time
					lowercase					=		{'''time''': time.time()}

					gc.collect()
					torch.cuda.empty_cache()

					# CPU mem
					lowercase					=		psutil.Process().memory_info().rss
					cpu_peak_tracker.start()

					# GPU mem
					for i in range(torch.cuda.device_count()	):
										lowercase					=		torch.cuda.memory_allocated(lowerCAmelCase__	)
					torch.cuda.reset_peak_memory_stats()

					return measures



def  UpperCamelCase					(							lowerCAmelCase__	):
					'''simple docstring'''
					# Time
					lowercase					=		{'''time''': time.time() - start_measures['''time''']}

					gc.collect()
					torch.cuda.empty_cache()

					# CPU mem
					lowercase					=		(psutil.Process().memory_info().rss - start_measures['''cpu''']) / 2**20
					lowercase					=		(cpu_peak_tracker.stop() - start_measures['''cpu''']) / 2**20

					# GPU mem
					for i in range(torch.cuda.device_count()	):
										lowercase					=		(torch.cuda.memory_allocated(lowerCAmelCase__	) - start_measures[str(lowerCAmelCase__	)]) / 2**20
										lowercase					=		(torch.cuda.max_memory_allocated(lowerCAmelCase__	) - start_measures[str(lowerCAmelCase__	)]) / 2**20

					return measures



def  UpperCamelCase					(							lowerCAmelCase__				,    lowerCAmelCase__	):
					'''simple docstring'''
					print(f'{description}:'	)
					print(f'- Time: {measures["time"]:.2f}s'	)
					for i in range(torch.cuda.device_count()	):
										print(f'- GPU {i} allocated: {measures[str(lowerCAmelCase__	)]:.2f}MiB'	)
										lowercase					=		measures[f'{i}-peak']
										print(f'- GPU {i} peak: {peak:.2f}MiB'	)
					print(f'- CPU RAM allocated: {measures["cpu"]:.2f}MiB'	)
					print(f'- CPU RAM peak: {measures["cpu-peak"]:.2f}MiB'	)






def  UpperCamelCase					(							lowerCAmelCase__				,    lowerCAmelCase__	):
					'''simple docstring'''
					return int((input_a, input_a).count(0	) == 0	)



def  UpperCamelCase					(							):
					'''simple docstring'''
					assert and_gate(0				,    0	) == 0
					assert and_gate(0				,    1	) == 0
					assert and_gate(1				,    0	) == 0
					assert and_gate(1				,    1	) == 1


if __name__ == "__main__":
							test_and_gate()
							print(and_gate(1, 0))
							print(and_gate(0, 0))
							print(and_gate(0, 1))
							print(and_gate(1, 1))




