util.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. import importlib
  2. import torch
  3. import numpy as np
  4. from collections import abc
  5. from einops import rearrange
  6. from functools import partial
  7. import multiprocessing as mp
  8. from threading import Thread
  9. from queue import Queue
  10. from inspect import isfunction
  11. from PIL import Image, ImageDraw, ImageFont
  12. def log_txt_as_img(wh, xc, size=10):
  13. # wh a tuple of (width, height)
  14. # xc a list of captions to plot
  15. b = len(xc)
  16. txts = list()
  17. for bi in range(b):
  18. txt = Image.new("RGB", wh, color="white")
  19. draw = ImageDraw.Draw(txt)
  20. font = ImageFont.truetype('data/DejaVuSans.ttf', size=size)
  21. nc = int(40 * (wh[0] / 256))
  22. lines = "\n".join(xc[bi][start:start + nc] for start in range(0, len(xc[bi]), nc))
  23. try:
  24. draw.text((0, 0), lines, fill="black", font=font)
  25. except UnicodeEncodeError:
  26. print("Cant encode string for logging. Skipping.")
  27. txt = np.array(txt).transpose(2, 0, 1) / 127.5 - 1.0
  28. txts.append(txt)
  29. txts = np.stack(txts)
  30. txts = torch.tensor(txts)
  31. return txts
  32. def ismap(x):
  33. if not isinstance(x, torch.Tensor):
  34. return False
  35. return (len(x.shape) == 4) and (x.shape[1] > 3)
  36. def isimage(x):
  37. if not isinstance(x, torch.Tensor):
  38. return False
  39. return (len(x.shape) == 4) and (x.shape[1] == 3 or x.shape[1] == 1)
  40. def exists(x):
  41. return x is not None
  42. def default(val, d):
  43. if exists(val):
  44. return val
  45. return d() if isfunction(d) else d
  46. def mean_flat(tensor):
  47. """
  48. https://github.com/openai/guided-diffusion/blob/27c20a8fab9cb472df5d6bdd6c8d11c8f430b924/guided_diffusion/nn.py#L86
  49. Take the mean over all non-batch dimensions.
  50. """
  51. return tensor.mean(dim=list(range(1, len(tensor.shape))))
  52. def count_params(model, verbose=False):
  53. total_params = sum(p.numel() for p in model.parameters())
  54. if verbose:
  55. print(f"{model.__class__.__name__} has {total_params * 1.e-6:.2f} M params.")
  56. return total_params
  57. def instantiate_from_config(config):
  58. if not "target" in config:
  59. if config == '__is_first_stage__':
  60. return None
  61. elif config == "__is_unconditional__":
  62. return None
  63. raise KeyError("Expected key `target` to instantiate.")
  64. return get_obj_from_str(config["target"])(**config.get("params", dict()))
  65. def get_obj_from_str(string, reload=False):
  66. module, cls = string.rsplit(".", 1)
  67. if reload:
  68. module_imp = importlib.import_module(module)
  69. importlib.reload(module_imp)
  70. return getattr(importlib.import_module(module, package=None), cls)
  71. def _do_parallel_data_prefetch(func, Q, data, idx, idx_to_fn=False):
  72. # create dummy dataset instance
  73. # run prefetching
  74. if idx_to_fn:
  75. res = func(data, worker_id=idx)
  76. else:
  77. res = func(data)
  78. Q.put([idx, res])
  79. Q.put("Done")
  80. def parallel_data_prefetch(
  81. func: callable, data, n_proc, target_data_type="ndarray", cpu_intensive=True, use_worker_id=False
  82. ):
  83. # if target_data_type not in ["ndarray", "list"]:
  84. # raise ValueError(
  85. # "Data, which is passed to parallel_data_prefetch has to be either of type list or ndarray."
  86. # )
  87. if isinstance(data, np.ndarray) and target_data_type == "list":
  88. raise ValueError("list expected but function got ndarray.")
  89. elif isinstance(data, abc.Iterable):
  90. if isinstance(data, dict):
  91. print(
  92. f'WARNING:"data" argument passed to parallel_data_prefetch is a dict: Using only its values and disregarding keys.'
  93. )
  94. data = list(data.values())
  95. if target_data_type == "ndarray":
  96. data = np.asarray(data)
  97. else:
  98. data = list(data)
  99. else:
  100. raise TypeError(
  101. f"The data, that shall be processed parallel has to be either an np.ndarray or an Iterable, but is actually {type(data)}."
  102. )
  103. if cpu_intensive:
  104. Q = mp.Queue(1000)
  105. proc = mp.Process
  106. else:
  107. Q = Queue(1000)
  108. proc = Thread
  109. # spawn processes
  110. if target_data_type == "ndarray":
  111. arguments = [
  112. [func, Q, part, i, use_worker_id]
  113. for i, part in enumerate(np.array_split(data, n_proc))
  114. ]
  115. else:
  116. step = (
  117. int(len(data) / n_proc + 1)
  118. if len(data) % n_proc != 0
  119. else int(len(data) / n_proc)
  120. )
  121. arguments = [
  122. [func, Q, part, i, use_worker_id]
  123. for i, part in enumerate(
  124. [data[i: i + step] for i in range(0, len(data), step)]
  125. )
  126. ]
  127. processes = []
  128. for i in range(n_proc):
  129. p = proc(target=_do_parallel_data_prefetch, args=arguments[i])
  130. processes += [p]
  131. # start processes
  132. print(f"Start prefetching...")
  133. import time
  134. start = time.time()
  135. gather_res = [[] for _ in range(n_proc)]
  136. try:
  137. for p in processes:
  138. p.start()
  139. k = 0
  140. while k < n_proc:
  141. # get result
  142. res = Q.get()
  143. if res == "Done":
  144. k += 1
  145. else:
  146. gather_res[res[0]] = res[1]
  147. except Exception as e:
  148. print("Exception: ", e)
  149. for p in processes:
  150. p.terminate()
  151. raise e
  152. finally:
  153. for p in processes:
  154. p.join()
  155. print(f"Prefetching complete. [{time.time() - start} sec.]")
  156. if target_data_type == 'ndarray':
  157. if not isinstance(gather_res[0], np.ndarray):
  158. return np.concatenate([np.asarray(r) for r in gather_res], axis=0)
  159. # order outputs
  160. return np.concatenate(gather_res, axis=0)
  161. elif target_data_type == 'list':
  162. out = []
  163. for r in gather_res:
  164. out.extend(r)
  165. return out
  166. else:
  167. return gather_res