| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939 |
- import errno
- import os
- import shutil
- import tempfile
- import unittest
- from collections import namedtuple
- from typing import List
- import caffe2.python.hypothesis_test_util as htu
- import hypothesis.strategies as st
- import numpy as np
- import torch
- from torch import Tensor
- from caffe2.proto import caffe2_pb2
- from caffe2.python import core, test_util, workspace, model_helper, brew
- from hypothesis import given, settings
- class TestWorkspace(unittest.TestCase):
- def setUp(self):
- self.net = core.Net("test-net")
- self.testblob_ref = self.net.ConstantFill(
- [], "testblob", shape=[1, 2, 3, 4], value=1.0
- )
- workspace.ResetWorkspace()
- def testRootFolder(self):
- self.assertEqual(workspace.ResetWorkspace(), True)
- self.assertEqual(workspace.RootFolder(), ".")
- self.assertEqual(workspace.ResetWorkspace("/tmp/caffe-workspace-test"), True)
- self.assertEqual(workspace.RootFolder(), "/tmp/caffe-workspace-test")
- def testWorkspaceHasBlobWithNonexistingName(self):
- self.assertEqual(workspace.HasBlob("non-existing"), False)
- def testRunOperatorOnce(self):
- self.assertEqual(
- workspace.RunOperatorOnce(self.net.Proto().op[0].SerializeToString()), True
- )
- self.assertEqual(workspace.HasBlob("testblob"), True)
- blobs = workspace.Blobs()
- self.assertEqual(len(blobs), 1)
- self.assertEqual(blobs[0], "testblob")
- def testGetOperatorCost(self):
- op = core.CreateOperator(
- "Conv2D",
- ["X", "W"],
- ["Y"],
- stride_h=1,
- stride_w=1,
- pad_t=1,
- pad_l=1,
- pad_b=1,
- pad_r=1,
- kernel=3,
- )
- X = np.zeros((1, 8, 8, 8))
- W = np.zeros((1, 1, 3, 3))
- workspace.FeedBlob("X", X)
- workspace.FeedBlob("W", W)
- op_cost = workspace.GetOperatorCost(op.SerializeToString(), ["X", "W"])
- self.assertTupleEqual(
- op_cost,
- namedtuple("Cost", ["flops", "bytes_written", "bytes_read"])(
- 1152, 256, 4168
- ),
- )
- def testRunNetOnce(self):
- self.assertEqual(
- workspace.RunNetOnce(self.net.Proto().SerializeToString()), True
- )
- self.assertEqual(workspace.HasBlob("testblob"), True)
- def testCurrentWorkspaceWrapper(self):
- self.assertNotIn("testblob", workspace.C.Workspace.current.blobs)
- self.assertEqual(
- workspace.RunNetOnce(self.net.Proto().SerializeToString()), True
- )
- self.assertEqual(workspace.HasBlob("testblob"), True)
- self.assertIn("testblob", workspace.C.Workspace.current.blobs)
- workspace.ResetWorkspace()
- self.assertNotIn("testblob", workspace.C.Workspace.current.blobs)
- def testRunPlan(self):
- plan = core.Plan("test-plan")
- plan.AddStep(core.ExecutionStep("test-step", self.net))
- self.assertEqual(workspace.RunPlan(plan.Proto().SerializeToString()), True)
- self.assertEqual(workspace.HasBlob("testblob"), True)
- def testRunPlanInBackground(self):
- plan = core.Plan("test-plan")
- plan.AddStep(core.ExecutionStep("test-step", self.net))
- background_plan = workspace.RunPlanInBackground(plan)
- while not background_plan.is_done():
- pass
- self.assertEqual(background_plan.is_succeeded(), True)
- self.assertEqual(workspace.HasBlob("testblob"), True)
- def testConstructPlanFromSteps(self):
- step = core.ExecutionStep("test-step-as-plan", self.net)
- self.assertEqual(workspace.RunPlan(step), True)
- self.assertEqual(workspace.HasBlob("testblob"), True)
- def testResetWorkspace(self):
- self.assertEqual(
- workspace.RunNetOnce(self.net.Proto().SerializeToString()), True
- )
- self.assertEqual(workspace.HasBlob("testblob"), True)
- self.assertEqual(workspace.ResetWorkspace(), True)
- self.assertEqual(workspace.HasBlob("testblob"), False)
- def testTensorAccess(self):
- ws = workspace.C.Workspace()
- """ test in-place modification """
- ws.create_blob("tensor").feed(np.array([1.1, 1.2, 1.3]))
- tensor = ws.blobs["tensor"].tensor()
- tensor.data[0] = 3.3
- val = np.array([3.3, 1.2, 1.3])
- np.testing.assert_array_equal(tensor.data, val)
- np.testing.assert_array_equal(ws.blobs["tensor"].fetch(), val)
- """ test in-place initialization """
- tensor.init([2, 3], core.DataType.INT32)
- for x in range(2):
- for y in range(3):
- tensor.data[x, y] = 0
- tensor.data[1, 1] = 100
- val = np.zeros([2, 3], dtype=np.int32)
- val[1, 1] = 100
- np.testing.assert_array_equal(tensor.data, val)
- np.testing.assert_array_equal(ws.blobs["tensor"].fetch(), val)
- """ strings cannot be initialized from python """
- with self.assertRaises(RuntimeError):
- tensor.init([3, 4], core.DataType.STRING)
- """ feed (copy) data into tensor """
- val = np.array([[b"abc", b"def"], [b"ghi", b"jkl"]], dtype=np.object)
- tensor.feed(val)
- self.assertEquals(tensor.data[0, 0], b"abc")
- np.testing.assert_array_equal(ws.blobs["tensor"].fetch(), val)
- val = np.array([1.1, 10.2])
- tensor.feed(val)
- val[0] = 5.2
- self.assertEquals(tensor.data[0], 1.1)
- """ fetch (copy) data from tensor """
- val = np.array([1.1, 1.2])
- tensor.feed(val)
- val2 = tensor.fetch()
- tensor.data[0] = 5.2
- val3 = tensor.fetch()
- np.testing.assert_array_equal(val, val2)
- self.assertEquals(val3[0], 5.2)
- def testFetchFeedBlob(self):
- self.assertEqual(
- workspace.RunNetOnce(self.net.Proto().SerializeToString()), True
- )
- fetched = workspace.FetchBlob("testblob")
- # check if fetched is correct.
- self.assertEqual(fetched.shape, (1, 2, 3, 4))
- np.testing.assert_array_equal(fetched, 1.0)
- fetched[:] = 2.0
- self.assertEqual(workspace.FeedBlob("testblob", fetched), True)
- fetched_again = workspace.FetchBlob("testblob")
- self.assertEqual(fetched_again.shape, (1, 2, 3, 4))
- np.testing.assert_array_equal(fetched_again, 2.0)
- def testFetchFeedBlobViaBlobReference(self):
- self.assertEqual(
- workspace.RunNetOnce(self.net.Proto().SerializeToString()), True
- )
- fetched = workspace.FetchBlob(self.testblob_ref)
- # check if fetched is correct.
- self.assertEqual(fetched.shape, (1, 2, 3, 4))
- np.testing.assert_array_equal(fetched, 1.0)
- fetched[:] = 2.0
- self.assertEqual(workspace.FeedBlob(self.testblob_ref, fetched), True)
- fetched_again = workspace.FetchBlob("testblob") # fetch by name now
- self.assertEqual(fetched_again.shape, (1, 2, 3, 4))
- np.testing.assert_array_equal(fetched_again, 2.0)
- def testFetchFeedBlobTypes(self):
- for dtype in [
- np.float16,
- np.float32,
- np.float64,
- np.bool,
- np.int8,
- np.int16,
- np.int32,
- np.int64,
- np.uint8,
- np.uint16,
- ]:
- try:
- rng = np.iinfo(dtype).max * 2
- except ValueError:
- rng = 1000
- data = ((np.random.rand(2, 3, 4) - 0.5) * rng).astype(dtype)
- self.assertEqual(workspace.FeedBlob("testblob_types", data), True)
- fetched_back = workspace.FetchBlob("testblob_types")
- self.assertEqual(fetched_back.shape, (2, 3, 4))
- self.assertEqual(fetched_back.dtype, dtype)
- np.testing.assert_array_equal(fetched_back, data)
- def testFetchFeedBlobBool(self):
- """Special case for bool to ensure coverage of both true and false."""
- data = np.zeros((2, 3, 4)).astype(np.bool)
- data.flat[::2] = True
- self.assertEqual(workspace.FeedBlob("testblob_types", data), True)
- fetched_back = workspace.FetchBlob("testblob_types")
- self.assertEqual(fetched_back.shape, (2, 3, 4))
- self.assertEqual(fetched_back.dtype, np.bool)
- np.testing.assert_array_equal(fetched_back, data)
- def testGetBlobSizeBytes(self):
- for dtype in [
- np.float16,
- np.float32,
- np.float64,
- np.bool,
- np.int8,
- np.int16,
- np.int32,
- np.int64,
- np.uint8,
- np.uint16,
- ]:
- data = np.random.randn(2, 3).astype(dtype)
- self.assertTrue(workspace.FeedBlob("testblob_sizeBytes", data), True)
- self.assertEqual(
- workspace.GetBlobSizeBytes("testblob_sizeBytes"),
- 6 * np.dtype(dtype).itemsize,
- )
- strs1 = np.array([b"Hello World!", b"abcd"])
- strs2 = np.array([b"element1", b"element2"])
- strs1_len, strs2_len = 0, 0
- for str in strs1:
- strs1_len += len(str)
- for str in strs2:
- strs2_len += len(str)
- self.assertTrue(workspace.FeedBlob("testblob_str1", strs1), True)
- self.assertTrue(workspace.FeedBlob("testblob_str2", strs2), True)
- # size of blob "testblob_str1" = size_str1 * meta_.itemsize() + strs1_len
- # size of blob "testblob_str2" = size_str2 * meta_.itemsize() + strs2_len
- self.assertEqual(
- workspace.GetBlobSizeBytes("testblob_str1")
- - workspace.GetBlobSizeBytes("testblob_str2"),
- strs1_len - strs2_len,
- )
- def testFetchFeedBlobZeroDim(self):
- data = np.empty(shape=(2, 0, 3), dtype=np.float32)
- self.assertEqual(workspace.FeedBlob("testblob_empty", data), True)
- fetched_back = workspace.FetchBlob("testblob_empty")
- self.assertEqual(fetched_back.shape, (2, 0, 3))
- self.assertEqual(fetched_back.dtype, np.float32)
- def testFetchFeedLongStringTensor(self):
- # long strings trigger array of object creation
- strs = np.array(
- [
- b" ".join(10 * [b"long string"]),
- b" ".join(128 * [b"very long string"]),
- b"small \0\1\2 string",
- b"Hello, world! I have special \0 symbols \1!",
- ]
- )
- workspace.FeedBlob("my_str_tensor", strs)
- strs2 = workspace.FetchBlob("my_str_tensor")
- self.assertEqual(strs.shape, strs2.shape)
- for i in range(0, strs.shape[0]):
- self.assertEqual(strs[i], strs2[i])
- def testFetchFeedShortStringTensor(self):
- # small strings trigger NPY_STRING array
- strs = np.array([b"elem1", b"elem 2", b"element 3"])
- workspace.FeedBlob("my_str_tensor_2", strs)
- strs2 = workspace.FetchBlob("my_str_tensor_2")
- self.assertEqual(strs.shape, strs2.shape)
- for i in range(0, strs.shape[0]):
- self.assertEqual(strs[i], strs2[i])
- def testFetchFeedPlainString(self):
- # this is actual string, not a tensor of strings
- s = b"Hello, world! I have special \0 symbols \1!"
- workspace.FeedBlob("my_plain_string", s)
- s2 = workspace.FetchBlob("my_plain_string")
- self.assertEqual(s, s2)
- def testFetchBlobs(self):
- s1 = b"test1"
- s2 = b"test2"
- workspace.FeedBlob("s1", s1)
- workspace.FeedBlob("s2", s2)
- fetch1, fetch2 = workspace.FetchBlobs(["s1", "s2"])
- self.assertEquals(s1, fetch1)
- self.assertEquals(s2, fetch2)
- def testFetchFeedViaBlobDict(self):
- self.assertEqual(
- workspace.RunNetOnce(self.net.Proto().SerializeToString()), True
- )
- fetched = workspace.blobs["testblob"]
- # check if fetched is correct.
- self.assertEqual(fetched.shape, (1, 2, 3, 4))
- np.testing.assert_array_equal(fetched, 1.0)
- fetched[:] = 2.0
- workspace.blobs["testblob"] = fetched
- fetched_again = workspace.blobs["testblob"]
- self.assertEqual(fetched_again.shape, (1, 2, 3, 4))
- np.testing.assert_array_equal(fetched_again, 2.0)
- self.assertTrue("testblob" in workspace.blobs)
- self.assertFalse("non_existant" in workspace.blobs)
- self.assertEqual(len(workspace.blobs), 1)
- for key in workspace.blobs:
- self.assertEqual(key, "testblob")
- def testTorchInterop(self):
- workspace.RunOperatorOnce(
- core.CreateOperator(
- "ConstantFill", [], "foo", shape=(4,), value=2, dtype=10
- )
- )
- t = workspace.FetchTorch("foo")
- t.resize_(5)
- t[4] = t[2] = 777
- np.testing.assert_array_equal(t.numpy(), np.array([2, 2, 777, 2, 777]))
- np.testing.assert_array_equal(
- workspace.FetchBlob("foo"), np.array([2, 2, 777, 2, 777])
- )
- z = torch.ones((4,), dtype=torch.int64)
- workspace.FeedBlob("bar", z)
- workspace.RunOperatorOnce(
- core.CreateOperator("Reshape", ["bar"], ["bar", "_"], shape=(2, 2))
- )
- z[0, 1] = 123
- np.testing.assert_array_equal(
- workspace.FetchBlob("bar"), np.array([[1, 123], [1, 1]])
- )
- np.testing.assert_array_equal(z, np.array([[1, 123], [1, 1]]))
- class TestMultiWorkspaces(unittest.TestCase):
- def setUp(self):
- workspace.SwitchWorkspace("default")
- workspace.ResetWorkspace()
- def testCreateWorkspace(self):
- self.net = core.Net("test-net")
- self.net.ConstantFill([], "testblob", shape=[1, 2, 3, 4], value=1.0)
- self.assertEqual(
- workspace.RunNetOnce(self.net.Proto().SerializeToString()), True
- )
- self.assertEqual(workspace.HasBlob("testblob"), True)
- self.assertEqual(workspace.SwitchWorkspace("test", True), None)
- self.assertEqual(workspace.HasBlob("testblob"), False)
- self.assertEqual(workspace.SwitchWorkspace("default"), None)
- self.assertEqual(workspace.HasBlob("testblob"), True)
- try:
- # The following should raise an error.
- workspace.SwitchWorkspace("non-existing")
- # so this should never happen.
- self.assertEqual(True, False)
- except RuntimeError:
- pass
- workspaces = workspace.Workspaces()
- self.assertTrue("default" in workspaces)
- self.assertTrue("test" in workspaces)
- @unittest.skipIf(not workspace.has_gpu_support, "No gpu support.")
- class TestWorkspaceGPU(test_util.TestCase):
- def setUp(self):
- workspace.ResetWorkspace()
- self.net = core.Net("test-net")
- self.net.ConstantFill([], "testblob", shape=[1, 2, 3, 4], value=1.0)
- self.net.RunAllOnGPU()
- def testFetchBlobGPU(self):
- self.assertEqual(
- workspace.RunNetOnce(self.net.Proto().SerializeToString()), True
- )
- fetched = workspace.FetchBlob("testblob")
- # check if fetched is correct.
- self.assertEqual(fetched.shape, (1, 2, 3, 4))
- np.testing.assert_array_equal(fetched, 1.0)
- fetched[:] = 2.0
- self.assertEqual(workspace.FeedBlob("testblob", fetched), True)
- fetched_again = workspace.FetchBlob("testblob")
- self.assertEqual(fetched_again.shape, (1, 2, 3, 4))
- np.testing.assert_array_equal(fetched_again, 2.0)
- def testGetGpuPeerAccessPattern(self):
- pattern = workspace.GetGpuPeerAccessPattern()
- self.assertEqual(type(pattern), np.ndarray)
- self.assertEqual(pattern.ndim, 2)
- self.assertEqual(pattern.shape[0], pattern.shape[1])
- self.assertEqual(pattern.shape[0], workspace.NumGpuDevices())
- @unittest.skipIf(
- not workspace.has_cuda_support, "Tensor interop doesn't yet work on ROCm"
- )
- def testTorchInterop(self):
- # CUDA has convenient mem stats, let's use them to make sure we didn't
- # leak memory
- initial_mem = torch.cuda.memory_allocated()
- workspace.RunOperatorOnce(
- core.CreateOperator(
- "ConstantFill",
- [],
- "foo",
- shape=(4,),
- value=2,
- dtype=10,
- device_option=core.DeviceOption(workspace.GpuDeviceType),
- )
- )
- t = workspace.FetchTorch("foo")
- t.resize_(5)
- self.assertTrue(t.is_cuda)
- t[4] = t[2] = 777
- np.testing.assert_array_equal(t.cpu().numpy(), np.array([2, 2, 777, 2, 777]))
- np.testing.assert_array_equal(
- workspace.FetchBlob("foo"), np.array([2, 2, 777, 2, 777])
- )
- z = torch.ones((4,), dtype=torch.int64, device="cuda")
- workspace.FeedBlob("bar", z)
- workspace.RunOperatorOnce(
- core.CreateOperator(
- "Reshape",
- ["bar"],
- ["bar", "_"],
- shape=(2, 2),
- device_option=core.DeviceOption(workspace.GpuDeviceType),
- )
- )
- z[0, 1] = 123
- np.testing.assert_array_equal(
- workspace.FetchBlob("bar"), np.array([[1, 123], [1, 1]])
- )
- np.testing.assert_array_equal(z.cpu(), np.array([[1, 123], [1, 1]]))
- self.assertGreater(torch.cuda.memory_allocated(), initial_mem)
- # clean up everything
- del t
- del z
- workspace.ResetWorkspace()
- self.assertEqual(torch.cuda.memory_allocated(), initial_mem)
- @unittest.skipIf(not workspace.C.use_mkldnn, "No MKLDNN support.")
- class TestWorkspaceIDEEP(test_util.TestCase):
- def testFeedFetchBlobIDEEP(self):
- arr = np.random.randn(2, 3).astype(np.float32)
- workspace.FeedBlob("testblob_ideep", arr, core.DeviceOption(caffe2_pb2.IDEEP))
- fetched = workspace.FetchBlob("testblob_ideep")
- np.testing.assert_array_equal(arr, fetched)
- class TestImmedibate(test_util.TestCase):
- def testImmediateEnterExit(self):
- workspace.StartImmediate(i_know=True)
- self.assertTrue(workspace.IsImmediate())
- workspace.StopImmediate()
- self.assertFalse(workspace.IsImmediate())
- def testImmediateRunsCorrectly(self):
- workspace.StartImmediate(i_know=True)
- net = core.Net("test-net")
- net.ConstantFill([], "testblob", shape=[1, 2, 3, 4], value=1.0)
- self.assertEqual(workspace.ImmediateBlobs(), ["testblob"])
- content = workspace.FetchImmediate("testblob")
- # Also, the immediate mode should not invade the original namespace,
- # so we check if this is so.
- with self.assertRaises(RuntimeError):
- workspace.FetchBlob("testblob")
- np.testing.assert_array_equal(content, 1.0)
- content[:] = 2.0
- self.assertTrue(workspace.FeedImmediate("testblob", content))
- np.testing.assert_array_equal(workspace.FetchImmediate("testblob"), 2.0)
- workspace.StopImmediate()
- with self.assertRaises(RuntimeError):
- content = workspace.FetchImmediate("testblob")
- def testImmediateRootFolder(self):
- workspace.StartImmediate(i_know=True)
- # for testing we will look into the _immediate_root_folder variable
- # but in normal usage you should not access that.
- self.assertTrue(len(workspace._immediate_root_folder) > 0)
- root_folder = workspace._immediate_root_folder
- self.assertTrue(os.path.isdir(root_folder))
- workspace.StopImmediate()
- self.assertTrue(len(workspace._immediate_root_folder) == 0)
- # After termination, immediate mode should have the root folder
- # deleted.
- self.assertFalse(os.path.exists(root_folder))
- class TestCppEnforceAsException(test_util.TestCase):
- def testEnforce(self):
- op = core.CreateOperator("Relu", ["X"], ["Y"])
- with self.assertRaises(RuntimeError):
- workspace.RunOperatorOnce(op)
- class TestCWorkspace(htu.HypothesisTestCase):
- def test_net_execution(self):
- ws = workspace.C.Workspace()
- self.assertEqual(ws.nets, {})
- self.assertEqual(ws.blobs, {})
- net = core.Net("test-net")
- net.ConstantFill([], "testblob", shape=[1, 2, 3, 4], value=1.0)
- ws.create_net(net)
- # If we do not specify overwrite, this should raise an error.
- with self.assertRaises(RuntimeError):
- ws.create_net(net)
- # But, if we specify overwrite, this should pass.
- ws.create_net(net, True)
- # Overwrite can also be a kwarg.
- ws.create_net(net, overwrite=True)
- self.assertIn("testblob", ws.blobs)
- self.assertEqual(len(ws.nets), 1)
- net_name = net.Proto().name
- self.assertIn("test-net", net_name)
- net = ws.nets[net_name].run()
- blob = ws.blobs["testblob"]
- np.testing.assert_array_equal(
- np.ones((1, 2, 3, 4), dtype=np.float32), blob.fetch()
- )
- @given(name=st.text(), value=st.floats(min_value=-1, max_value=1.0))
- def test_operator_run(self, name, value):
- ws = workspace.C.Workspace()
- op = core.CreateOperator("ConstantFill", [], [name], shape=[1], value=value)
- ws.run(op)
- self.assertIn(name, ws.blobs)
- np.testing.assert_allclose(
- [value], ws.blobs[name].fetch(), atol=1e-4, rtol=1e-4
- )
- @given(
- blob_name=st.text(),
- net_name=st.text(),
- value=st.floats(min_value=-1, max_value=1.0),
- )
- def test_net_run(self, blob_name, net_name, value):
- ws = workspace.C.Workspace()
- net = core.Net(net_name)
- net.ConstantFill([], [blob_name], shape=[1], value=value)
- ws.run(net)
- self.assertIn(blob_name, ws.blobs)
- self.assertNotIn(net_name, ws.nets)
- np.testing.assert_allclose(
- [value], ws.blobs[blob_name].fetch(), atol=1e-4, rtol=1e-4
- )
- @given(
- blob_name=st.text(),
- net_name=st.text(),
- plan_name=st.text(),
- value=st.floats(min_value=-1, max_value=1.0),
- )
- def test_plan_run(self, blob_name, plan_name, net_name, value):
- ws = workspace.C.Workspace()
- plan = core.Plan(plan_name)
- net = core.Net(net_name)
- net.ConstantFill([], [blob_name], shape=[1], value=value)
- plan.AddStep(core.ExecutionStep("step", nets=[net], num_iter=1))
- ws.run(plan)
- self.assertIn(blob_name, ws.blobs)
- self.assertIn(net.Name(), ws.nets)
- np.testing.assert_allclose(
- [value], ws.blobs[blob_name].fetch(), atol=1e-4, rtol=1e-4
- )
- @given(
- blob_name=st.text(),
- net_name=st.text(),
- value=st.floats(min_value=-1, max_value=1.0),
- )
- def test_net_create(self, blob_name, net_name, value):
- ws = workspace.C.Workspace()
- net = core.Net(net_name)
- net.ConstantFill([], [blob_name], shape=[1], value=value)
- ws.create_net(net).run()
- self.assertIn(blob_name, ws.blobs)
- self.assertIn(net.Name(), ws.nets)
- np.testing.assert_allclose(
- [value], ws.blobs[blob_name].fetch(), atol=1e-4, rtol=1e-4
- )
- @given(
- name=st.text(),
- value=htu.tensor(),
- device_option=st.sampled_from(htu.device_options),
- )
- def test_array_serde(self, name, value, device_option):
- ws = workspace.C.Workspace()
- ws.create_blob(name).feed(value, device_option=device_option)
- self.assertIn(name, ws.blobs)
- blob = ws.blobs[name]
- np.testing.assert_equal(value, ws.blobs[name].fetch())
- serde_blob = ws.create_blob("{}_serde".format(name))
- serde_blob.deserialize(blob.serialize(name))
- np.testing.assert_equal(value, serde_blob.fetch())
- @given(name=st.text(), value=st.text())
- def test_string_serde(self, name, value):
- value = value.encode("ascii", "ignore")
- ws = workspace.C.Workspace()
- ws.create_blob(name).feed(value)
- self.assertIn(name, ws.blobs)
- blob = ws.blobs[name]
- self.assertEqual(value, ws.blobs[name].fetch())
- serde_blob = ws.create_blob("{}_serde".format(name))
- serde_blob.deserialize(blob.serialize(name))
- self.assertEqual(value, serde_blob.fetch())
- def test_exception(self):
- ws = workspace.C.Workspace()
- with self.assertRaises(TypeError):
- ws.create_net("...")
- class TestPredictor(unittest.TestCase):
- def _create_model(self):
- m = model_helper.ModelHelper()
- y = brew.fc(
- m,
- "data",
- "y",
- dim_in=4,
- dim_out=2,
- weight_init=("ConstantFill", dict(value=1.0)),
- bias_init=("ConstantFill", dict(value=0.0)),
- axis=0,
- )
- m.net.AddExternalOutput(y)
- return m
- # Use this test with a bigger model to see how using Predictor allows to
- # avoid issues with low protobuf size limit in Python
- #
- # def test_predictor_predefined(self):
- # workspace.ResetWorkspace()
- # path = 'caffe2/caffe2/test/assets/'
- # with open(path + 'squeeze_predict_net.pb') as f:
- # self.predict_net = f.read()
- # with open(path + 'squeeze_init_net.pb') as f:
- # self.init_net = f.read()
- # self.predictor = workspace.Predictor(self.init_net, self.predict_net)
- # inputs = [np.zeros((1, 3, 256, 256), dtype='f')]
- # outputs = self.predictor.run(inputs)
- # self.assertEqual(len(outputs), 1)
- # self.assertEqual(outputs[0].shape, (1, 1000, 1, 1))
- # self.assertAlmostEqual(outputs[0][0][0][0][0], 5.19026289e-05)
- def test_predictor_memory_model(self):
- workspace.ResetWorkspace()
- m = self._create_model()
- workspace.FeedBlob("data", np.zeros([4], dtype="float32"))
- self.predictor = workspace.Predictor(
- workspace.StringifyProto(m.param_init_net.Proto()),
- workspace.StringifyProto(m.net.Proto()),
- )
- inputs = np.array([1, 3, 256, 256], dtype="float32")
- outputs = self.predictor.run([inputs])
- np.testing.assert_array_almost_equal(
- np.array([[516, 516]], dtype="float32"), outputs
- )
- class TestTransform(htu.HypothesisTestCase):
- @given(
- input_dim=st.integers(min_value=1, max_value=10),
- output_dim=st.integers(min_value=1, max_value=10),
- batch_size=st.integers(min_value=1, max_value=10),
- )
- def test_simple_transform(self, input_dim, output_dim, batch_size):
- m = model_helper.ModelHelper()
- fc1 = brew.fc(m, "data", "fc1", dim_in=input_dim, dim_out=output_dim)
- fc2 = brew.fc(m, fc1, "fc2", dim_in=output_dim, dim_out=output_dim)
- conv = brew.conv(
- m,
- fc2,
- "conv",
- dim_in=output_dim,
- dim_out=output_dim,
- use_cudnn=True,
- engine="CUDNN",
- kernel=3,
- )
- conv.Relu([], conv).Softmax([], "pred").LabelCrossEntropy(
- ["label"], ["xent"]
- ).AveragedLoss([], "loss")
- transformed_net_proto = workspace.ApplyTransform("ConvToNNPack", m.net.Proto())
- self.assertEqual(transformed_net_proto.op[2].engine, "NNPACK")
- @given(
- input_dim=st.integers(min_value=1, max_value=10),
- output_dim=st.integers(min_value=1, max_value=10),
- batch_size=st.integers(min_value=1, max_value=10),
- )
- @settings(deadline=10000)
- def test_registry_invalid(self, input_dim, output_dim, batch_size):
- m = model_helper.ModelHelper()
- brew.fc(m, "data", "fc1", dim_in=input_dim, dim_out=output_dim)
- with self.assertRaises(RuntimeError):
- workspace.ApplyTransform("definitely_not_a_real_transform", m.net.Proto())
- @given(value=st.floats(min_value=-1, max_value=1))
- @settings(deadline=10000)
- def test_apply_transform_if_faster(self, value):
- init_net = core.Net("init_net")
- init_net.ConstantFill([], ["data"], shape=[5, 5, 5, 5], value=value)
- init_net.ConstantFill([], ["conv_w"], shape=[5, 5, 3, 3], value=value)
- init_net.ConstantFill([], ["conv_b"], shape=[5], value=value)
- self.assertEqual(
- workspace.RunNetOnce(init_net.Proto().SerializeToString()), True
- )
- m = model_helper.ModelHelper()
- conv = brew.conv(
- m,
- "data",
- "conv",
- dim_in=5,
- dim_out=5,
- kernel=3,
- use_cudnn=True,
- engine="CUDNN",
- )
- conv.Relu([], conv).Softmax([], "pred").AveragedLoss([], "loss")
- self.assertEqual(workspace.RunNetOnce(m.net.Proto().SerializeToString()), True)
- proto = workspace.ApplyTransformIfFaster(
- "ConvToNNPack", m.net.Proto(), init_net.Proto()
- )
- self.assertEqual(workspace.RunNetOnce(proto.SerializeToString()), True)
- proto = workspace.ApplyTransformIfFaster(
- "ConvToNNPack",
- m.net.Proto(),
- init_net.Proto(),
- warmup_runs=10,
- main_runs=100,
- improvement_threshold=2.0,
- )
- self.assertEqual(workspace.RunNetOnce(proto.SerializeToString()), True)
- class MyModule(torch.jit.ScriptModule):
- def __init__(self):
- super(MyModule, self).__init__()
- self.mult = torch.nn.Parameter(torch.tensor([[1, 2, 3, 4, 5.0]]))
- @torch.jit.script_method
- def forward(self, x):
- return self.mult.mm(x)
- @torch.jit.script_method
- def multi_input(self, x: torch.Tensor, y: torch.Tensor, z: int = 2) -> torch.Tensor:
- return x + y + z
- @torch.jit.script_method
- def multi_input_tensor_list(self, tensor_list: List[Tensor]) -> Tensor:
- return tensor_list[0] + tensor_list[1] + tensor_list[2]
- @torch.jit.script_method
- def multi_output(self, x):
- return (x, x + 1)
- @unittest.skipIf(
- "ScriptModule" not in core._REGISTERED_OPERATORS,
- "Script module integration in Caffe2 is not enabled",
- )
- class TestScriptModule(test_util.TestCase):
- def _createFeedModule(self):
- workspace.FeedBlob("m", MyModule())
- def testCreation(self):
- m = MyModule()
- workspace.FeedBlob("module", m)
- m2 = workspace.FetchBlob("module")
- self.assertTrue(m2 is not None)
- def testForward(self):
- self._createFeedModule()
- val = np.random.rand(5, 5).astype(np.float32)
- param = np.array([[1, 2, 3, 4, 5]]).astype(np.float32)
- workspace.FeedBlob("w", val)
- workspace.RunOperatorOnce(
- core.CreateOperator("ScriptModule", ["m", "w"], ["y"])
- )
- np.testing.assert_almost_equal(
- workspace.FetchBlob("y"), np.matmul(param, val), decimal=5
- )
- def testMultiInputOutput(self):
- self._createFeedModule()
- val = np.random.rand(5, 5).astype(np.float32)
- workspace.FeedBlob("w", val)
- val2 = np.random.rand(5, 5).astype(np.float32)
- workspace.FeedBlob("w2", val2)
- workspace.RunOperatorOnce(
- core.CreateOperator(
- "ScriptModule", ["m", "w", "w2"], ["y"], method="multi_input"
- )
- )
- workspace.RunOperatorOnce(
- core.CreateOperator(
- "ScriptModule", ["m", "w"], ["y1", "y2"], method="multi_output"
- )
- )
- np.testing.assert_almost_equal(
- workspace.FetchBlob("y"), val + val2 + 2, decimal=5
- )
- np.testing.assert_almost_equal(workspace.FetchBlob("y1"), val, decimal=5)
- np.testing.assert_almost_equal(workspace.FetchBlob("y2"), val + 1, decimal=5)
- def testMultiTensorListInput(self):
- self._createFeedModule()
- val = np.random.rand(5, 5).astype(np.float32)
- workspace.FeedBlob("w", val)
- val2 = np.random.rand(5, 5).astype(np.float32)
- workspace.FeedBlob("w2", val2)
- val3 = np.random.rand(5, 5).astype(np.float32)
- workspace.FeedBlob("w3", val3)
- workspace.RunOperatorOnce(
- core.CreateOperator(
- "ScriptModule",
- ["m", "w", "w2", "w3"],
- ["y"],
- method="multi_input_tensor_list",
- pass_inputs_as_tensor_list=True,
- )
- )
- np.testing.assert_almost_equal(
- workspace.FetchBlob("y"), val + val2 + val3, decimal=5
- )
- def testSerialization(self):
- tmpdir = tempfile.mkdtemp()
- try:
- self._createFeedModule()
- workspace.RunOperatorOnce(
- core.CreateOperator(
- "Save",
- ["m"],
- [],
- absolute_path=1,
- db=os.path.join(tmpdir, "db"),
- db_type="minidb",
- )
- )
- workspace.ResetWorkspace()
- self.assertFalse(workspace.HasBlob("m"))
- workspace.RunOperatorOnce(
- core.CreateOperator(
- "Load",
- [],
- [],
- absolute_path=1,
- db=os.path.join(tmpdir, "db"),
- db_type="minidb",
- load_all=1,
- )
- )
- self.assertTrue(workspace.HasBlob("m"))
- # TODO: make caffe2 side load return python-sided module
- # right now it returns the base class (torch._C.ScriptModule)
- # self.assertTrue(isinstance(workspace.FetchBlob('m'), torch.jit.ScriptModule))
- # do something with the module
- val = np.random.rand(5, 5).astype(np.float32)
- param = np.array([[1, 2, 3, 4, 5]]).astype(np.float32)
- workspace.FeedBlob("w", val)
- workspace.RunOperatorOnce(
- core.CreateOperator("ScriptModule", ["m", "w"], ["y"])
- )
- np.testing.assert_almost_equal(
- workspace.FetchBlob("y"), np.matmul(param, val), decimal=5
- )
- finally:
- # clean up temp folder.
- try:
- shutil.rmtree(tmpdir)
- except OSError as e:
- if e.errno != errno.ENOENT:
- raise
- class TestScriptModuleFromString(TestScriptModule):
- def _createFeedModule(self):
- workspace.RunOperatorOnce(
- core.CreateOperator(
- "ScriptModuleLoad",
- [],
- ["m"],
- serialized_binary=self._get_modules_bytes(MyModule()),
- )
- )
- def _get_modules_bytes(self, the_module):
- import io
- buffer = io.BytesIO()
- torch.jit.save(the_module, buffer)
- return buffer.getvalue()
- if __name__ == "__main__":
- unittest.main()
|