|
| 1 | +import unittest |
| 2 | +import pickle |
| 3 | + |
1 | 4 | import numpy as np |
2 | 5 | import numpy.core.umath_tests as ut |
3 | 6 |
|
4 | 7 | from numba import void, float32, jit, guvectorize |
5 | 8 | from numba.np.ufunc import GUVectorize |
6 | 9 | from numba.tests.support import tag, TestCase |
7 | | -import unittest |
8 | 10 |
|
9 | 11 |
|
10 | 12 | def matmulcore(A, B, C): |
@@ -281,5 +283,119 @@ class TestGUVectorizeScalarParallel(TestGUVectorizeScalar): |
281 | 283 | target = 'parallel' |
282 | 284 |
|
283 | 285 |
|
| 286 | +class TestGUVectorizePickling(TestCase): |
| 287 | + def test_pickle_gufunc_non_dyanmic(self): |
| 288 | + """Non-dynamic gufunc. |
| 289 | + """ |
| 290 | + @guvectorize(["f8,f8[:]"], "()->()") |
| 291 | + def double(x, out): |
| 292 | + out[:] = x * 2 |
| 293 | + |
| 294 | + # pickle |
| 295 | + ser = pickle.dumps(double) |
| 296 | + cloned = pickle.loads(ser) |
| 297 | + |
| 298 | + # attributes carried over |
| 299 | + self.assertEqual(cloned._frozen, double._frozen) |
| 300 | + self.assertEqual(cloned.identity, double.identity) |
| 301 | + self.assertEqual(cloned.is_dynamic, double.is_dynamic) |
| 302 | + self.assertEqual(cloned.gufunc_builder._sigs, |
| 303 | + double.gufunc_builder._sigs) |
| 304 | + # expected value of attributes |
| 305 | + self.assertTrue(cloned._frozen) |
| 306 | + |
| 307 | + cloned.disable_compile() |
| 308 | + self.assertTrue(cloned._frozen) |
| 309 | + |
| 310 | + # scalar version |
| 311 | + self.assertPreciseEqual(double(0.5), cloned(0.5)) |
| 312 | + # array version |
| 313 | + arr = np.arange(10) |
| 314 | + self.assertPreciseEqual(double(arr), cloned(arr)) |
| 315 | + |
| 316 | + def test_pickle_gufunc_dyanmic_null_init(self): |
| 317 | + """Dynamic gufunc w/o prepopulating before pickling. |
| 318 | + """ |
| 319 | + @guvectorize("()->()", identity=1) |
| 320 | + def double(x, out): |
| 321 | + out[:] = x * 2 |
| 322 | + |
| 323 | + # pickle |
| 324 | + ser = pickle.dumps(double) |
| 325 | + cloned = pickle.loads(ser) |
| 326 | + |
| 327 | + # attributes carried over |
| 328 | + self.assertEqual(cloned._frozen, double._frozen) |
| 329 | + self.assertEqual(cloned.identity, double.identity) |
| 330 | + self.assertEqual(cloned.is_dynamic, double.is_dynamic) |
| 331 | + self.assertEqual(cloned.gufunc_builder._sigs, |
| 332 | + double.gufunc_builder._sigs) |
| 333 | + # expected value of attributes |
| 334 | + self.assertFalse(cloned._frozen) |
| 335 | + |
| 336 | + # scalar version |
| 337 | + expect = np.zeros(1) |
| 338 | + got = np.zeros(1) |
| 339 | + double(0.5, out=expect) |
| 340 | + cloned(0.5, out=got) |
| 341 | + self.assertPreciseEqual(expect, got) |
| 342 | + # array version |
| 343 | + arr = np.arange(10) |
| 344 | + expect = np.zeros_like(arr) |
| 345 | + got = np.zeros_like(arr) |
| 346 | + double(arr, out=expect) |
| 347 | + cloned(arr, out=got) |
| 348 | + self.assertPreciseEqual(expect, got) |
| 349 | + |
| 350 | + def test_pickle_gufunc_dyanmic_initialized(self): |
| 351 | + """Dynamic gufunc prepopulated before pickling. |
| 352 | +
|
| 353 | + Once unpickled, we disable compilation to verify that the gufunc |
| 354 | + compilation state is carried over. |
| 355 | + """ |
| 356 | + @guvectorize("()->()", identity=1) |
| 357 | + def double(x, out): |
| 358 | + out[:] = x * 2 |
| 359 | + |
| 360 | + # prepopulate scalar |
| 361 | + expect = np.zeros(1) |
| 362 | + got = np.zeros(1) |
| 363 | + double(0.5, out=expect) |
| 364 | + # prepopulate array |
| 365 | + arr = np.arange(10) |
| 366 | + expect = np.zeros_like(arr) |
| 367 | + got = np.zeros_like(arr) |
| 368 | + double(arr, out=expect) |
| 369 | + |
| 370 | + # pickle |
| 371 | + ser = pickle.dumps(double) |
| 372 | + cloned = pickle.loads(ser) |
| 373 | + |
| 374 | + # attributes carried over |
| 375 | + self.assertEqual(cloned._frozen, double._frozen) |
| 376 | + self.assertEqual(cloned.identity, double.identity) |
| 377 | + self.assertEqual(cloned.is_dynamic, double.is_dynamic) |
| 378 | + self.assertEqual(cloned.gufunc_builder._sigs, |
| 379 | + double.gufunc_builder._sigs) |
| 380 | + # expected value of attributes |
| 381 | + self.assertFalse(cloned._frozen) |
| 382 | + |
| 383 | + # disable compilation |
| 384 | + cloned.disable_compile() |
| 385 | + self.assertTrue(cloned._frozen) |
| 386 | + # scalar version |
| 387 | + expect = np.zeros(1) |
| 388 | + got = np.zeros(1) |
| 389 | + double(0.5, out=expect) |
| 390 | + cloned(0.5, out=got) |
| 391 | + self.assertPreciseEqual(expect, got) |
| 392 | + # array version |
| 393 | + expect = np.zeros_like(arr) |
| 394 | + got = np.zeros_like(arr) |
| 395 | + double(arr, out=expect) |
| 396 | + cloned(arr, out=got) |
| 397 | + self.assertPreciseEqual(expect, got) |
| 398 | + |
| 399 | + |
284 | 400 | if __name__ == '__main__': |
285 | 401 | unittest.main() |
0 commit comments