test_unity_cpp.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. import ggml
  2. import ctypes
  3. import torch
  4. import pytest
  5. import numpy as np
  6. from pathlib import Path
  7. from typing import Iterator
  8. from ggml import NativeObj
  9. from ggml_convert import convert_model
  10. Ctx = ggml.ggml_context_p
  11. UNITY_MODELS = Path(__file__).parent / "examples/unity/models"
  12. PARAMS_16MB = ggml.ggml_init_params(mem_size=16 * 1024 * 1024, mem_buffer=None)
  13. @pytest.fixture(name="ctx")
  14. def _ctx() -> Iterator[Ctx]:
  15. """Allocate a new context with 16 MB of memory"""
  16. try:
  17. ctx = ggml.ggml_init(params=PARAMS_16MB)
  18. yield ctx
  19. finally:
  20. ggml.ggml_free(ctx)
  21. def test_ggml_bindings_work(ctx: Ctx) -> None:
  22. # Instantiate tensors
  23. x = ggml.ggml_new_tensor_1d(ctx, ggml.GGML_TYPE_F32, 1)
  24. a = ggml.ggml_new_tensor_1d(ctx, ggml.GGML_TYPE_F32, 1)
  25. b = ggml.ggml_new_tensor_1d(ctx, ggml.GGML_TYPE_F32, 1)
  26. # Use ggml operations to build a computational graph
  27. x2 = ggml.ggml_mul(ctx, x, x)
  28. f = ggml.ggml_add(ctx, ggml.ggml_mul(ctx, a, x2), b)
  29. gf = ggml.ggml_build_forward(f)
  30. # Set the input values
  31. ggml.ggml_set_f32(x, 2.0)
  32. ggml.ggml_set_f32(a, 3.0)
  33. ggml.ggml_set_f32(b, 4.0)
  34. # Compute the graph
  35. ggml.ggml_graph_compute_with_ctx(ctx, ctypes.pointer(gf), 1)
  36. # Get the output value
  37. output = ggml.ggml_get_f32_1d(f, 0)
  38. assert output == 16.0
  39. def test_shape_works(ctx: Ctx) -> None:
  40. a = ggml.ggml_new_tensor_1d(ctx, ggml.GGML_TYPE_F32, 10)
  41. assert ggml.shape(a) == (10,)
  42. b = ggml.ggml_new_tensor_2d(ctx, ggml.GGML_TYPE_F32, 11, 21)
  43. assert ggml.shape(b) == (11, 21)
  44. c = ggml.ggml_new_tensor_3d(ctx, ggml.GGML_TYPE_F32, 12, 22, 32)
  45. assert ggml.shape(c) == (12, 22, 32)
  46. @pytest.mark.xfail(
  47. reason="TODO: understand diff between ggml strides and numpy strides"
  48. )
  49. def test_strides_works(ctx: Ctx) -> None:
  50. a = ggml.ggml_new_tensor_1d(ctx, ggml.GGML_TYPE_F32, 10)
  51. assert ggml.strides(a) == np.ones((10,), dtype=np.float32).strides
  52. b = ggml.ggml_new_tensor_2d(ctx, ggml.GGML_TYPE_F32, 11, 21)
  53. assert ggml.strides(b) == np.ones((11, 21), dtype=np.float32).strides
  54. c = ggml.ggml_new_tensor_3d(ctx, ggml.GGML_TYPE_F32, 12, 22, 32)
  55. assert ggml.strides(c) == np.ones((12, 22, 32), dtype=np.float32).strides
  56. def test_to_numpy_works_with_f32(ctx: Ctx) -> None:
  57. a = ggml.ggml_new_tensor_1d(ctx, ggml.GGML_TYPE_F32, 10)
  58. a = ggml.ggml_set_f32(a, 2.14)
  59. assert np.allclose(ggml.to_numpy(a), np.ones((10,)) * 2.14)
  60. b = ggml.ggml_new_tensor_2d(ctx, ggml.GGML_TYPE_F32, 11, 21)
  61. assert np.allclose(ggml.to_numpy(b), np.zeros((11, 21)))
  62. c = ggml.ggml_new_tensor_3d(ctx, ggml.GGML_TYPE_F32, 12, 22, 32)
  63. assert np.allclose(ggml.to_numpy(c), np.zeros((12, 22, 32)))
  64. def test_from_numpy_works_with_f32(ctx: Ctx) -> None:
  65. a = np.random.normal(size=(10,)).astype(dtype=np.float32)
  66. ga = ggml.from_numpy(ctx, a)
  67. assert np.allclose(a, ggml.to_numpy(ga))
  68. a = np.random.normal(size=(11, 21)).astype(dtype=np.float32)
  69. ga = ggml.from_numpy(ctx, a)
  70. assert np.allclose(a, ggml.to_numpy(ga))
  71. a = np.random.normal(size=(12, 22, 32)).astype(dtype=np.float32)
  72. ga = ggml.from_numpy(ctx, a)
  73. assert np.allclose(a, ggml.to_numpy(ga))
  74. def test_to_numpy_works_with_f16(ctx: Ctx) -> None:
  75. # We explicitly fill the tensor otherwise they might have non-zero values in them.
  76. a = ggml.ggml_new_tensor_1d(ctx, ggml.GGML_TYPE_F16, 10)
  77. a = ggml.ggml_set_f32(a, 2.14)
  78. assert np.allclose(ggml.to_numpy(a), np.ones((10,), dtype=np.float16) * 2.14)
  79. b = ggml.ggml_new_tensor_2d(ctx, ggml.GGML_TYPE_F16, 11, 21)
  80. b = ggml.ggml_set_f32(b, 4.18)
  81. assert np.allclose(ggml.to_numpy(b), np.ones((11, 21), dtype=np.float16) * 4.18)
  82. c = ggml.ggml_new_tensor_3d(ctx, ggml.GGML_TYPE_F16, 12, 22, 32)
  83. c = ggml.ggml_set_f32(c, 3.16)
  84. assert np.allclose(ggml.to_numpy(c), np.ones((12, 22, 32), dtype=np.float16) * 3.16)
  85. def test_from_numpy_works_with_f16(ctx: Ctx) -> None:
  86. a = np.random.normal(size=(10,)).astype(dtype=np.float16)
  87. ga = ggml.from_numpy(ctx, a)
  88. assert np.allclose(a, ggml.to_numpy(ga))
  89. a = np.random.normal(size=(11, 21)).astype(dtype=np.float16)
  90. ga = ggml.from_numpy(ctx, a)
  91. assert np.allclose(a, ggml.to_numpy(ga))
  92. a = np.random.normal(size=(12, 22, 32)).astype(dtype=np.float16)
  93. ga = ggml.from_numpy(ctx, a)
  94. assert np.allclose(a, ggml.to_numpy(ga))
  95. def test_unity_model_load(ctx: Ctx) -> None:
  96. model, vocab = ggml.unity_model_load(UNITY_MODELS / "unity-large/ggml-model.bin")
  97. print(model, vocab)
  98. example = ggml.from_file(
  99. ctx, UNITY_MODELS / "unity-large/seqs_before_conformer_block.bin", (1024, 137)
  100. )
  101. with ggml.MeasureArena() as arena:
  102. graph = ggml.unity_audio_encoder_graph(model, example)
  103. # TODO: why the extra memory ?
  104. mem_size = ggml.ggml_allocr_alloc_graph(arena.ptr, graph) + ggml.GGML_MEM_ALIGN
  105. with ggml.FixedSizeArena(mem_size) as allocr:
  106. print(
  107. f"unity_audio_encoder_graph: compute buffer size: {mem_size/1024/1024} MB"
  108. )
  109. eval_res_ptr = ggml.unity_eval(allocr, model, example, 1)
  110. eval_res = eval_res_ptr.contents
  111. inpL = ggml.to_numpy(eval_res.nodes[eval_res.n_nodes - 1])
  112. expected_raw = "-0.1308,0.0346,-0.2656,0.2873,-0.0104,0.0574,0.4033,-0.1125,-0.0460,-0.0496"
  113. expected = map(float, expected_raw.split(","))
  114. assert np.allclose(inpL[0, :10], list(expected), atol=1e-4)
  115. def test_unity_model_load2(ctx: Ctx, tmp_path: Path) -> None:
  116. model_file = Path(__file__).parent / "seamlessM4T_medium.ggml"
  117. if not model_file.exists():
  118. convert_model("seamlessM4T_medium", model_file)
  119. hparams_header_file = model_file.with_suffix(".hparams.h")
  120. hparams_struct = hparams_header_file.read_text().strip()
  121. actual_code = (UNITY_MODELS.parent / "unity_model_loader.h").read_text()
  122. # breakpoint()
  123. # assert hparams_struct in actual_code
  124. model = ggml.load_unity_ggml_file(model_file)
  125. print(model)