Skip to content

Commit 8a09ee9

Browse files
authored
Merge pull request #1015 from codeflash-ai/gpu-sync-instrumentation
Non-CPU device synchronization for accurate profiling
2 parents 9eec46a + 00edfb1 commit 8a09ee9

5 files changed

Lines changed: 2064 additions & 2 deletions

File tree

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
"""
2+
Utility functions used in CompEcon
3+
4+
Based routines found in the CompEcon toolbox by Miranda and Fackler.
5+
6+
References
7+
----------
8+
Miranda, Mario J, and Paul L Fackler. Applied Computational Economics
9+
and Finance, MIT Press, 2002.
10+
11+
"""
12+
from functools import reduce
13+
import numpy as np
14+
import torch
15+
16+
def _gridmake2(x1, x2):
17+
"""
18+
Expands two vectors (or matrices) into a matrix where rows span the
19+
cartesian product of combinations of the input arrays. Each column of the
20+
input arrays will correspond to one column of the output matrix.
21+
22+
Parameters
23+
----------
24+
x1 : np.ndarray
25+
First vector to be expanded.
26+
27+
x2 : np.ndarray
28+
Second vector to be expanded.
29+
30+
Returns
31+
-------
32+
out : np.ndarray
33+
The cartesian product of combinations of the input arrays.
34+
35+
Notes
36+
-----
37+
Based of original function ``gridmake2`` in CompEcon toolbox by
38+
Miranda and Fackler.
39+
40+
References
41+
----------
42+
Miranda, Mario J, and Paul L Fackler. Applied Computational Economics
43+
and Finance, MIT Press, 2002.
44+
45+
"""
46+
if x1.ndim == 1 and x2.ndim == 1:
47+
return np.column_stack([np.tile(x1, x2.shape[0]),
48+
np.repeat(x2, x1.shape[0])])
49+
elif x1.ndim > 1 and x2.ndim == 1:
50+
first = np.tile(x1, (x2.shape[0], 1))
51+
second = np.repeat(x2, x1.shape[0])
52+
return np.column_stack([first, second])
53+
else:
54+
raise NotImplementedError("Come back here")
55+
56+
57+
def _gridmake2_torch(x1: torch.Tensor, x2: torch.Tensor) -> torch.Tensor:
58+
"""
59+
PyTorch version of _gridmake2.
60+
61+
Expands two tensors into a matrix where rows span the cartesian product
62+
of combinations of the input tensors. Each column of the input tensors
63+
will correspond to one column of the output matrix.
64+
65+
Parameters
66+
----------
67+
x1 : torch.Tensor
68+
First tensor to be expanded.
69+
70+
x2 : torch.Tensor
71+
Second tensor to be expanded.
72+
73+
Returns
74+
-------
75+
out : torch.Tensor
76+
The cartesian product of combinations of the input tensors.
77+
78+
Notes
79+
-----
80+
Based on original function ``gridmake2`` in CompEcon toolbox by
81+
Miranda and Fackler.
82+
83+
References
84+
----------
85+
Miranda, Mario J, and Paul L Fackler. Applied Computational Economics
86+
and Finance, MIT Press, 2002.
87+
88+
"""
89+
if x1.dim() == 1 and x2.dim() == 1:
90+
# tile x1 by x2.shape[0] times, repeat_interleave x2 by x1.shape[0]
91+
first = x1.tile(x2.shape[0])
92+
second = x2.repeat_interleave(x1.shape[0])
93+
return torch.column_stack([first, second])
94+
elif x1.dim() > 1 and x2.dim() == 1:
95+
# tile x1 along first dimension
96+
first = x1.tile(x2.shape[0], 1)
97+
second = x2.repeat_interleave(x1.shape[0])
98+
return torch.column_stack([first, second])
99+
else:
100+
raise NotImplementedError("Come back here")
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
import numpy as np
2+
import pytest
3+
from numpy.testing import assert_array_equal
4+
5+
from code_to_optimize.discrete_riccati import _gridmake2
6+
7+
8+
class TestGridmake2With1DArrays:
9+
"""Tests for _gridmake2 with two 1D arrays."""
10+
11+
def test_basic_two_element_arrays(self):
12+
"""Test basic cartesian product of two 2-element arrays."""
13+
x1 = np.array([1, 2])
14+
x2 = np.array([3, 4])
15+
result = _gridmake2(x1, x2)
16+
17+
# Expected: x1 is tiled len(x2) times, x2 is repeated len(x1) times
18+
expected = np.array([
19+
[1, 3],
20+
[2, 3],
21+
[1, 4],
22+
[2, 4]
23+
])
24+
assert_array_equal(result, expected)
25+
26+
def test_different_length_arrays(self):
27+
"""Test cartesian product with arrays of different lengths."""
28+
x1 = np.array([1, 2, 3])
29+
x2 = np.array([10, 20])
30+
result = _gridmake2(x1, x2)
31+
32+
# Result should have len(x1) * len(x2) = 6 rows
33+
expected = np.array([
34+
[1, 10],
35+
[2, 10],
36+
[3, 10],
37+
[1, 20],
38+
[2, 20],
39+
[3, 20]
40+
])
41+
assert_array_equal(result, expected)
42+
assert result.shape == (6, 2)
43+
44+
def test_single_element_arrays(self):
45+
"""Test with single-element arrays."""
46+
x1 = np.array([5])
47+
x2 = np.array([7])
48+
result = _gridmake2(x1, x2)
49+
50+
expected = np.array([[5, 7]])
51+
assert_array_equal(result, expected)
52+
assert result.shape == (1, 2)
53+
54+
def test_single_element_with_multi_element(self):
55+
"""Test single-element array with multi-element array."""
56+
x1 = np.array([1])
57+
x2 = np.array([10, 20, 30])
58+
result = _gridmake2(x1, x2)
59+
60+
expected = np.array([
61+
[1, 10],
62+
[1, 20],
63+
[1, 30]
64+
])
65+
assert_array_equal(result, expected)
66+
67+
def test_float_arrays(self):
68+
"""Test with float arrays."""
69+
x1 = np.array([1.5, 2.5])
70+
x2 = np.array([0.1, 0.2])
71+
result = _gridmake2(x1, x2)
72+
73+
expected = np.array([
74+
[1.5, 0.1],
75+
[2.5, 0.1],
76+
[1.5, 0.2],
77+
[2.5, 0.2]
78+
])
79+
assert_array_equal(result, expected)
80+
81+
def test_negative_values(self):
82+
"""Test with negative values."""
83+
x1 = np.array([-1, 0, 1])
84+
x2 = np.array([-10, 10])
85+
result = _gridmake2(x1, x2)
86+
87+
expected = np.array([
88+
[-1, -10],
89+
[0, -10],
90+
[1, -10],
91+
[-1, 10],
92+
[0, 10],
93+
[1, 10]
94+
])
95+
assert_array_equal(result, expected)
96+
97+
def test_result_shape(self):
98+
"""Test that result shape is (len(x1)*len(x2), 2)."""
99+
x1 = np.array([1, 2, 3, 4])
100+
x2 = np.array([5, 6, 7])
101+
result = _gridmake2(x1, x2)
102+
103+
assert result.shape == (12, 2)
104+
105+
def test_larger_arrays(self):
106+
"""Test with larger arrays."""
107+
x1 = np.arange(10)
108+
x2 = np.arange(5)
109+
result = _gridmake2(x1, x2)
110+
111+
assert result.shape == (50, 2)
112+
# Verify first column is x1 tiled 5 times
113+
assert_array_equal(result[:10, 0], x1)
114+
assert_array_equal(result[10:20, 0], x1)
115+
# Verify second column is x2 repeated 10 times each
116+
assert all(result[:10, 1] == 0)
117+
assert all(result[10:20, 1] == 1)
118+
119+
120+
class TestGridmake2With2DFirst:
121+
"""Tests for _gridmake2 when x1 is 2D and x2 is 1D."""
122+
123+
def test_2d_first_1d_second(self):
124+
"""Test with 2D first array and 1D second array."""
125+
x1 = np.array([[1, 2], [3, 4]]) # 2 rows, 2 cols
126+
x2 = np.array([10, 20])
127+
result = _gridmake2(x1, x2)
128+
129+
# x1 is tiled len(x2) times vertically
130+
# x2 is repeated len(x1) times (2 rows)
131+
expected = np.array([
132+
[1, 2, 10],
133+
[3, 4, 10],
134+
[1, 2, 20],
135+
[3, 4, 20]
136+
])
137+
assert_array_equal(result, expected)
138+
139+
def test_2d_single_column(self):
140+
"""Test with 2D array having single column."""
141+
x1 = np.array([[1], [2], [3]]) # 3 rows, 1 col
142+
x2 = np.array([10, 20])
143+
result = _gridmake2(x1, x2)
144+
145+
expected = np.array([
146+
[1, 10],
147+
[2, 10],
148+
[3, 10],
149+
[1, 20],
150+
[2, 20],
151+
[3, 20]
152+
])
153+
assert_array_equal(result, expected)
154+
155+
def test_2d_multiple_columns(self):
156+
"""Test with 2D array having multiple columns."""
157+
x1 = np.array([[1, 2, 3], [4, 5, 6]]) # 2 rows, 3 cols
158+
x2 = np.array([100])
159+
result = _gridmake2(x1, x2)
160+
161+
expected = np.array([
162+
[1, 2, 3, 100],
163+
[4, 5, 6, 100]
164+
])
165+
assert_array_equal(result, expected)
166+
167+
168+
class TestGridmake2EdgeCases:
169+
"""Edge case tests for _gridmake2."""
170+
171+
def test_empty_arrays_raise_or_return_empty(self):
172+
"""Test behavior with empty arrays."""
173+
x1 = np.array([])
174+
x2 = np.array([1, 2])
175+
result = _gridmake2(x1, x2)
176+
# Empty x1 should result in empty output
177+
assert result.shape[0] == 0
178+
179+
def test_both_empty_arrays(self):
180+
"""Test with both empty arrays."""
181+
x1 = np.array([])
182+
x2 = np.array([])
183+
result = _gridmake2(x1, x2)
184+
assert result.shape[0] == 0
185+
186+
def test_integer_dtype_preserved(self):
187+
"""Test that integer dtype is handled correctly."""
188+
x1 = np.array([1, 2], dtype=np.int64)
189+
x2 = np.array([3, 4], dtype=np.int64)
190+
result = _gridmake2(x1, x2)
191+
assert result.dtype == np.int64
192+
193+
def test_float_dtype_preserved(self):
194+
"""Test that float dtype is handled correctly."""
195+
x1 = np.array([1.0, 2.0], dtype=np.float64)
196+
x2 = np.array([3.0, 4.0], dtype=np.float64)
197+
result = _gridmake2(x1, x2)
198+
assert result.dtype == np.float64
199+
200+
201+
class TestGridmake2NotImplemented:
202+
"""Tests for NotImplementedError cases."""
203+
204+
def test_both_2d_raises(self):
205+
"""Test that two 2D arrays raises NotImplementedError."""
206+
x1 = np.array([[1, 2], [3, 4]])
207+
x2 = np.array([[5, 6], [7, 8]])
208+
with pytest.raises(NotImplementedError):
209+
_gridmake2(x1, x2)
210+
211+
def test_1d_first_2d_second_raises(self):
212+
"""Test that 1D first and 2D second raises NotImplementedError."""
213+
x1 = np.array([1, 2])
214+
x2 = np.array([[5, 6], [7, 8]])
215+
with pytest.raises(NotImplementedError):
216+
_gridmake2(x1, x2)

0 commit comments

Comments
 (0)