| @@ -26,12 +26,6 @@ Global | |||||
| Debug|Any CPU = Debug|Any CPU | Debug|Any CPU = Debug|Any CPU | ||||
| Debug|x64 = Debug|x64 | Debug|x64 = Debug|x64 | ||||
| Debug|x86 = Debug|x86 | Debug|x86 = Debug|x86 | ||||
| Debug-Minimal|Any CPU = Debug-Minimal|Any CPU | |||||
| Debug-Minimal|x64 = Debug-Minimal|x64 | |||||
| Debug-Minimal|x86 = Debug-Minimal|x86 | |||||
| Publish|Any CPU = Publish|Any CPU | |||||
| Publish|x64 = Publish|x64 | |||||
| Publish|x86 = Publish|x86 | |||||
| Release|Any CPU = Release|Any CPU | Release|Any CPU = Release|Any CPU | ||||
| Release|x64 = Release|x64 | Release|x64 = Release|x64 | ||||
| Release|x86 = Release|x86 | Release|x86 = Release|x86 | ||||
| @@ -43,18 +37,6 @@ Global | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|x64.Build.0 = Debug|x64 | {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|x64.Build.0 = Debug|x64 | ||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|x86.ActiveCfg = Debug|Any CPU | {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|x86.Build.0 = Debug|Any CPU | {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug-Minimal|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug-Minimal|Any CPU.Build.0 = Debug|Any CPU | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug-Minimal|x64.ActiveCfg = Debug|x64 | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug-Minimal|x64.Build.0 = Debug|x64 | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug-Minimal|x86.ActiveCfg = Debug|Any CPU | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug-Minimal|x86.Build.0 = Debug|Any CPU | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Publish|Any CPU.ActiveCfg = Release|Any CPU | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Publish|Any CPU.Build.0 = Release|Any CPU | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Publish|x64.ActiveCfg = Release|x64 | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Publish|x64.Build.0 = Release|x64 | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Publish|x86.ActiveCfg = Release|Any CPU | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Publish|x86.Build.0 = Release|Any CPU | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Release|Any CPU.ActiveCfg = Release|Any CPU | {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Release|Any CPU.Build.0 = Release|Any CPU | {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Release|x64.ActiveCfg = Release|x64 | {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Release|x64.ActiveCfg = Release|x64 | ||||
| @@ -67,18 +49,6 @@ Global | |||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Debug|x64.Build.0 = Debug|x64 | {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Debug|x64.Build.0 = Debug|x64 | ||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Debug|x86.ActiveCfg = Debug|Any CPU | {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Debug|x86.Build.0 = Debug|Any CPU | {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Debug-Minimal|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Debug-Minimal|Any CPU.Build.0 = Debug|Any CPU | |||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Debug-Minimal|x64.ActiveCfg = Debug|x64 | |||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Debug-Minimal|x64.Build.0 = Debug|x64 | |||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Debug-Minimal|x86.ActiveCfg = Debug|Any CPU | |||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Debug-Minimal|x86.Build.0 = Debug|Any CPU | |||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Publish|Any CPU.ActiveCfg = Release|Any CPU | |||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Publish|Any CPU.Build.0 = Release|Any CPU | |||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Publish|x64.ActiveCfg = Release|x64 | |||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Publish|x64.Build.0 = Release|x64 | |||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Publish|x86.ActiveCfg = Release|Any CPU | |||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Publish|x86.Build.0 = Release|Any CPU | |||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Release|Any CPU.ActiveCfg = Release|Any CPU | {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Release|Any CPU.Build.0 = Release|Any CPU | {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Release|x64.ActiveCfg = Release|x64 | {3A6EB896-604F-4E25-B677-B8103BCF3D2E}.Release|x64.ActiveCfg = Release|x64 | ||||
| @@ -91,18 +61,6 @@ Global | |||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Debug|x64.Build.0 = Debug|x64 | {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Debug|x64.Build.0 = Debug|x64 | ||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Debug|x86.ActiveCfg = Debug|Any CPU | {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Debug|x86.Build.0 = Debug|Any CPU | {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Debug-Minimal|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Debug-Minimal|Any CPU.Build.0 = Debug|Any CPU | |||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Debug-Minimal|x64.ActiveCfg = Debug|x64 | |||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Debug-Minimal|x64.Build.0 = Debug|x64 | |||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Debug-Minimal|x86.ActiveCfg = Debug|Any CPU | |||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Debug-Minimal|x86.Build.0 = Debug|Any CPU | |||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Publish|Any CPU.ActiveCfg = Release|Any CPU | |||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Publish|Any CPU.Build.0 = Release|Any CPU | |||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Publish|x64.ActiveCfg = Release|x64 | |||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Publish|x64.Build.0 = Release|x64 | |||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Publish|x86.ActiveCfg = Release|Any CPU | |||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Publish|x86.Build.0 = Release|Any CPU | |||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Release|Any CPU.ActiveCfg = Release|Any CPU | {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Release|Any CPU.Build.0 = Release|Any CPU | {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Release|x64.ActiveCfg = Release|x64 | {23C28035-2FCE-41F3-9A12-E73CE8A5AE32}.Release|x64.ActiveCfg = Release|x64 | ||||
| @@ -115,18 +73,6 @@ Global | |||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Debug|x64.Build.0 = Debug|x64 | {03F06299-3F4B-4449-A709-3A647657BC0C}.Debug|x64.Build.0 = Debug|x64 | ||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Debug|x86.ActiveCfg = Debug|Any CPU | {03F06299-3F4B-4449-A709-3A647657BC0C}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Debug|x86.Build.0 = Debug|Any CPU | {03F06299-3F4B-4449-A709-3A647657BC0C}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Debug-Minimal|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Debug-Minimal|Any CPU.Build.0 = Debug|Any CPU | |||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Debug-Minimal|x64.ActiveCfg = Debug|Any CPU | |||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Debug-Minimal|x64.Build.0 = Debug|Any CPU | |||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Debug-Minimal|x86.ActiveCfg = Debug|Any CPU | |||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Debug-Minimal|x86.Build.0 = Debug|Any CPU | |||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Publish|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Publish|Any CPU.Build.0 = Debug|Any CPU | |||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Publish|x64.ActiveCfg = Debug|Any CPU | |||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Publish|x64.Build.0 = Debug|Any CPU | |||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Publish|x86.ActiveCfg = Debug|Any CPU | |||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Publish|x86.Build.0 = Debug|Any CPU | |||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Release|Any CPU.ActiveCfg = Release|Any CPU | {03F06299-3F4B-4449-A709-3A647657BC0C}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Release|Any CPU.Build.0 = Release|Any CPU | {03F06299-3F4B-4449-A709-3A647657BC0C}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| {03F06299-3F4B-4449-A709-3A647657BC0C}.Release|x64.ActiveCfg = Release|Any CPU | {03F06299-3F4B-4449-A709-3A647657BC0C}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| @@ -139,18 +85,6 @@ Global | |||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Debug|x64.Build.0 = Debug|x64 | {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Debug|x64.Build.0 = Debug|x64 | ||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Debug|x86.ActiveCfg = Debug|Any CPU | {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Debug|x86.Build.0 = Debug|Any CPU | {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Debug-Minimal|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Debug-Minimal|Any CPU.Build.0 = Debug|Any CPU | |||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Debug-Minimal|x64.ActiveCfg = Debug|x64 | |||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Debug-Minimal|x64.Build.0 = Debug|x64 | |||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Debug-Minimal|x86.ActiveCfg = Debug|Any CPU | |||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Debug-Minimal|x86.Build.0 = Debug|Any CPU | |||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Publish|Any CPU.ActiveCfg = Release|Any CPU | |||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Publish|Any CPU.Build.0 = Release|Any CPU | |||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Publish|x64.ActiveCfg = Debug|x64 | |||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Publish|x64.Build.0 = Debug|x64 | |||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Publish|x86.ActiveCfg = Release|Any CPU | |||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Publish|x86.Build.0 = Release|Any CPU | |||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Release|Any CPU.ActiveCfg = Release|Any CPU | {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Release|Any CPU.Build.0 = Release|Any CPU | {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Release|x64.ActiveCfg = Release|x64 | {49D71826-C03D-4FA7-9BAC-22C1327E65CF}.Release|x64.ActiveCfg = Release|x64 | ||||
| @@ -163,18 +97,6 @@ Global | |||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Debug|x64.Build.0 = Debug|x64 | {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Debug|x64.Build.0 = Debug|x64 | ||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Debug|x86.ActiveCfg = Debug|Any CPU | {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Debug|x86.Build.0 = Debug|Any CPU | {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Debug-Minimal|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Debug-Minimal|Any CPU.Build.0 = Debug|Any CPU | |||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Debug-Minimal|x64.ActiveCfg = Debug|Any CPU | |||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Debug-Minimal|x64.Build.0 = Debug|Any CPU | |||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Debug-Minimal|x86.ActiveCfg = Debug|Any CPU | |||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Debug-Minimal|x86.Build.0 = Debug|Any CPU | |||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Publish|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Publish|Any CPU.Build.0 = Debug|Any CPU | |||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Publish|x64.ActiveCfg = Debug|Any CPU | |||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Publish|x64.Build.0 = Debug|Any CPU | |||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Publish|x86.ActiveCfg = Debug|Any CPU | |||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Publish|x86.Build.0 = Debug|Any CPU | |||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Release|Any CPU.ActiveCfg = Release|Any CPU | {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Release|Any CPU.Build.0 = Release|Any CPU | {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Release|x64.ActiveCfg = Release|Any CPU | {1AB8108D-4FFE-4A16-88E7-328EAF686370}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| @@ -187,18 +109,6 @@ Global | |||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Debug|x64.Build.0 = Debug|x64 | {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Debug|x64.Build.0 = Debug|x64 | ||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Debug|x86.ActiveCfg = Debug|Any CPU | {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Debug|x86.Build.0 = Debug|Any CPU | {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Debug-Minimal|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Debug-Minimal|Any CPU.Build.0 = Debug|Any CPU | |||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Debug-Minimal|x64.ActiveCfg = Debug|Any CPU | |||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Debug-Minimal|x64.Build.0 = Debug|Any CPU | |||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Debug-Minimal|x86.ActiveCfg = Debug|Any CPU | |||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Debug-Minimal|x86.Build.0 = Debug|Any CPU | |||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Publish|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Publish|Any CPU.Build.0 = Debug|Any CPU | |||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Publish|x64.ActiveCfg = Debug|Any CPU | |||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Publish|x64.Build.0 = Debug|Any CPU | |||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Publish|x86.ActiveCfg = Debug|Any CPU | |||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Publish|x86.Build.0 = Debug|Any CPU | |||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Release|Any CPU.ActiveCfg = Release|Any CPU | {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Release|Any CPU.Build.0 = Release|Any CPU | {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Release|x64.ActiveCfg = Release|Any CPU | {F17AAECB-960A-4E18-A270-BAD776F0E55B}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| @@ -211,18 +121,6 @@ Global | |||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Debug|x64.Build.0 = Debug|x64 | {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Debug|x64.Build.0 = Debug|x64 | ||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Debug|x86.ActiveCfg = Debug|Any CPU | {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Debug|x86.Build.0 = Debug|Any CPU | {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Debug-Minimal|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Debug-Minimal|Any CPU.Build.0 = Debug|Any CPU | |||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Debug-Minimal|x64.ActiveCfg = Debug|Any CPU | |||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Debug-Minimal|x64.Build.0 = Debug|Any CPU | |||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Debug-Minimal|x86.ActiveCfg = Debug|Any CPU | |||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Debug-Minimal|x86.Build.0 = Debug|Any CPU | |||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Publish|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Publish|Any CPU.Build.0 = Debug|Any CPU | |||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Publish|x64.ActiveCfg = Debug|Any CPU | |||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Publish|x64.Build.0 = Debug|Any CPU | |||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Publish|x86.ActiveCfg = Debug|Any CPU | |||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Publish|x86.Build.0 = Debug|Any CPU | |||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Release|Any CPU.ActiveCfg = Release|Any CPU | {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Release|Any CPU.Build.0 = Release|Any CPU | {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Release|x64.ActiveCfg = Release|Any CPU | {84CA35F8-99FC-408E-8DF3-5AA175E5EFD3}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| @@ -235,18 +133,6 @@ Global | |||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Debug|x64.Build.0 = Debug|x64 | {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Debug|x64.Build.0 = Debug|x64 | ||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Debug|x86.ActiveCfg = Debug|Any CPU | {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Debug|x86.Build.0 = Debug|Any CPU | {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Debug-Minimal|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Debug-Minimal|Any CPU.Build.0 = Debug|Any CPU | |||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Debug-Minimal|x64.ActiveCfg = Debug|Any CPU | |||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Debug-Minimal|x64.Build.0 = Debug|Any CPU | |||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Debug-Minimal|x86.ActiveCfg = Debug|Any CPU | |||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Debug-Minimal|x86.Build.0 = Debug|Any CPU | |||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Publish|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Publish|Any CPU.Build.0 = Debug|Any CPU | |||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Publish|x64.ActiveCfg = Debug|Any CPU | |||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Publish|x64.Build.0 = Debug|Any CPU | |||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Publish|x86.ActiveCfg = Debug|Any CPU | |||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Publish|x86.Build.0 = Debug|Any CPU | |||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Release|Any CPU.ActiveCfg = Release|Any CPU | {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Release|Any CPU.Build.0 = Release|Any CPU | {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Release|x64.ActiveCfg = Release|Any CPU | {79EB56DF-E29E-4AE2-A7D9-FE403FD919BA}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| @@ -0,0 +1,64 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | |||||
| using System.Text; | |||||
| using System.Linq; | |||||
| using static Tensorflow.Binding; | |||||
| using System.Text.RegularExpressions; | |||||
| namespace Tensorflow | |||||
| { | |||||
| public class Diagnostician | |||||
| { | |||||
| public void Diagnose(string log) | |||||
| { | |||||
| var lines = File.ReadAllLines(log); | |||||
| foreach(var (i, line) in enumerate(lines)) | |||||
| { | |||||
| if(line.StartsWith("New Tensor ")) | |||||
| { | |||||
| var pointers = Regex.Matches(line, "0x[0-9a-f]{16}"); | |||||
| var tensorHandle = pointers[0].Value; | |||||
| var tensorDataHandle = pointers[1].Value; | |||||
| if (lines.Skip(i).Count(x => x.StartsWith("Delete Tensor ") | |||||
| && x.Contains(tensorHandle) | |||||
| && x.Contains(tensorDataHandle)) == 0) | |||||
| Console.WriteLine(line); | |||||
| } | |||||
| else if (line.StartsWith("New EagerTensorHandle ")) | |||||
| { | |||||
| var pointers = Regex.Matches(line, "0x[0-9a-f]{16}"); | |||||
| var tensorHandle = pointers[0].Value; | |||||
| var del = $"Delete EagerTensorHandle {tensorHandle}"; | |||||
| if (lines.Skip(i).Count(x => x == del) == 0) | |||||
| Console.WriteLine(line); | |||||
| } | |||||
| else if (line.StartsWith("Take EagerTensorHandle ")) | |||||
| { | |||||
| var pointers = Regex.Matches(line, "0x[0-9a-f]{16}"); | |||||
| var eagerTensorHandle = pointers[0].Value; | |||||
| var tensorHandle = pointers[1].Value; | |||||
| var delTensor = $"Delete Tensor {tensorHandle}"; | |||||
| var delEagerTensor = $"Delete EagerTensorHandle {eagerTensorHandle}"; | |||||
| if (lines.Skip(i).Count(x => x.StartsWith(delTensor)) == 0 | |||||
| || lines.Skip(i).Count(x => x.StartsWith(delEagerTensor)) == 0) | |||||
| Console.WriteLine(line); | |||||
| } | |||||
| else if (line.StartsWith("Created Resource ")) | |||||
| { | |||||
| var pointers = Regex.Matches(line, "0x[0-9a-f]{16}"); | |||||
| var eagerTensorHandle = pointers[0].Value; | |||||
| var delTensor = $"Deleted Resource {eagerTensorHandle}"; | |||||
| if (lines.Skip(i).Count(x => x.StartsWith(delTensor)) == 0) | |||||
| Console.WriteLine(line); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,152 @@ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using Tensorflow.Keras.ArgsDefinition; | |||||
| using Tensorflow.Keras.Engine.DataAdapters; | |||||
| using static Tensorflow.Binding; | |||||
| using static Tensorflow.KerasApi; | |||||
| namespace Tensorflow | |||||
| { | |||||
| class MemoryBasicTest | |||||
| { | |||||
| public Action<int, int> Placeholder | |||||
| => (epoch, iterate) => | |||||
| { | |||||
| var ph = array_ops.placeholder(tf.float32, (10, 512, 512, 3)); | |||||
| }; | |||||
| /// <summary> | |||||
| /// | |||||
| /// </summary> | |||||
| public Action<int, int> Constant | |||||
| => (epoch, iterate) => | |||||
| { | |||||
| var tensor = tf.constant(3112.0f); | |||||
| }; | |||||
| public Action<int, int> Constant2x3 | |||||
| => (epoch, iterate) => | |||||
| { | |||||
| var nd = np.arange(1000).reshape(10, 100); | |||||
| var tensor = tf.constant(nd); | |||||
| var data = tensor.numpy(); | |||||
| }; | |||||
| public Action<int, int> ConstantString | |||||
| => (epoch, iterate) => | |||||
| { | |||||
| var tensor = tf.constant(new string[] | |||||
| { | |||||
| "Biden immigration bill would put millions of illegal immigrants on 8-year fast-track to citizenship", | |||||
| "The Associated Press, which also reported that the eight-year path is in the bill.", | |||||
| "The bill would also include provisions to stem the flow of migration by addressing root causes of migration from south of the border." | |||||
| }); | |||||
| var data = tensor.numpy(); | |||||
| }; | |||||
| public Action<int, int> Variable | |||||
| => (epoch, iterate) => | |||||
| { | |||||
| var nd = np.arange(1 * 256 * 256 * 3).reshape(1, 256, 256, 3); | |||||
| ResourceVariable variable = tf.Variable(nd); | |||||
| }; | |||||
| public Action<int, int> VariableRead | |||||
| => (epoch, iterate) => | |||||
| { | |||||
| var nd = np.zeros(1 * 256 * 256 * 3).astype(np.float32).reshape(1, 256, 256, 3); | |||||
| ResourceVariable variable = tf.Variable(nd); | |||||
| var nd2 = np.arange(1 * 256 * 256 * 3).astype(np.float32).reshape(1, 256, 256, 3); | |||||
| variable.assign(nd2); | |||||
| for (int i = 0; i< 100; i++) | |||||
| { | |||||
| var v = variable.numpy(); | |||||
| } | |||||
| }; | |||||
| public Action<int, int> MathAdd | |||||
| => (epoch, iterate) => | |||||
| { | |||||
| var x = tf.constant(3112.0f); | |||||
| var y = tf.constant(3112.0f); | |||||
| var z = x + y; | |||||
| }; | |||||
| public Action<int, int> Gradient | |||||
| => (epoch, iterate) => | |||||
| { | |||||
| var w = tf.constant(3112.0f); | |||||
| using var tape = tf.GradientTape(); | |||||
| tape.watch(w); | |||||
| var loss = w * w; | |||||
| var grad = tape.gradient(loss, w); | |||||
| }; | |||||
| public Action<int, int> Conv2DWithTensor | |||||
| => (epoch, iterate) => | |||||
| { | |||||
| var input = array_ops.zeros((10, 32, 32, 3), dtypes.float32); | |||||
| var filter = array_ops.zeros((3, 3, 3, 32), dtypes.float32); | |||||
| var strides = new[] { 1, 1, 1, 1 }; | |||||
| var dilations = new[] { 1, 1, 1, 1 }; | |||||
| var results = tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, | |||||
| "Conv2D", null, | |||||
| null, | |||||
| input, filter, | |||||
| "strides", strides, | |||||
| "use_cudnn_on_gpu", true, | |||||
| "padding", "VALID", | |||||
| "explicit_paddings", new int[0], | |||||
| "data_format", "NHWC", | |||||
| "dilations", dilations); | |||||
| }; | |||||
| public Action<int, int> Conv2DWithVariable | |||||
| => (epoch, iterate) => | |||||
| { | |||||
| var input = array_ops.zeros((10, 32, 32, 3), dtypes.float32); | |||||
| var filter = tf.Variable(array_ops.zeros((3, 3, 3, 32), dtypes.float32)); | |||||
| var strides = new[] { 1, 1, 1, 1 }; | |||||
| var dilations = new[] { 1, 1, 1, 1 }; | |||||
| var results = tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, | |||||
| "Conv2D", null, | |||||
| null, | |||||
| input, filter, | |||||
| "strides", strides, | |||||
| "use_cudnn_on_gpu", true, | |||||
| "padding", "VALID", | |||||
| "explicit_paddings", new int[0], | |||||
| "data_format", "NHWC", | |||||
| "dilations", dilations); | |||||
| }; | |||||
| public Action<int, int> Dataset | |||||
| => (epoch, iterate) => | |||||
| { | |||||
| TensorShape shape = (16, 32, 32, 3); | |||||
| var images = np.arange(shape.size).astype(np.float32).reshape(shape.dims); | |||||
| var data_handler = new DataHandler(new DataHandlerArgs | |||||
| { | |||||
| X = images, | |||||
| BatchSize = 2, | |||||
| StepsPerEpoch = -1, | |||||
| InitialEpoch = 0, | |||||
| Epochs = 2, | |||||
| MaxQueueSize = 10, | |||||
| Workers = 1, | |||||
| UseMultiprocessing = false, | |||||
| StepsPerExecution = tf.Variable(1) | |||||
| }); | |||||
| /*foreach (var (_epoch, iterator) in data_handler.enumerate_epochs()) | |||||
| { | |||||
| foreach (var step in data_handler.steps()) | |||||
| iterator.next(); | |||||
| }*/ | |||||
| }; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,30 @@ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| using Tensorflow.Functions; | |||||
| using static Tensorflow.Binding; | |||||
| namespace Tensorflow | |||||
| { | |||||
| class MemoryFuncGraphTest | |||||
| { | |||||
| public Action<int, int> ConcreteFunction | |||||
| => (epoch, iterate) => | |||||
| { | |||||
| var func = new ConcreteFunction(Guid.NewGuid().ToString()); | |||||
| func.Enter(); | |||||
| var input = tf.placeholder(tf.float32); | |||||
| var output = permutation(input); | |||||
| func.ToGraph(input, output); | |||||
| func.Exit(); | |||||
| }; | |||||
| Tensor permutation(Tensor tensor) | |||||
| { | |||||
| TensorShape shape = (8, 64, 64, 3); | |||||
| var images = np.arange(shape.size).astype(np.float32).reshape(shape.dims); | |||||
| return tf.constant(images); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,51 @@ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using static Tensorflow.Binding; | |||||
| using static Tensorflow.KerasApi; | |||||
| namespace Tensorflow | |||||
| { | |||||
| class MemoryKerasTest | |||||
| { | |||||
| public Action<int, int> Conv2DLayer | |||||
| => (epoch, iterate) => | |||||
| { | |||||
| var input_shape = new int[] { 4, 512, 512, 3 }; | |||||
| var x = tf.random.normal(input_shape); | |||||
| var conv2d = keras.layers.Conv2D(2, 3, activation: keras.activations.Relu); | |||||
| var output = conv2d.Apply(x); | |||||
| }; | |||||
| public Action<int, int> InputLayer | |||||
| => (epoch, iterate) => | |||||
| { | |||||
| TensorShape shape = (32, 256, 256, 3); // 48M | |||||
| var images = np.arange(shape.size).astype(np.float32).reshape(shape.dims); | |||||
| var inputs = keras.Input((shape.dims[1], shape.dims[2], 3)); | |||||
| var conv2d = keras.layers.Conv2D(32, kernel_size: (3, 3), | |||||
| activation: keras.activations.Linear); | |||||
| var outputs = conv2d.Apply(inputs); | |||||
| }; | |||||
| public Action<int, int> Prediction | |||||
| => (epoch, iterate) => | |||||
| { | |||||
| TensorShape shape = (32, 256, 256, 3); // 48M | |||||
| var images = np.arange(shape.size).astype(np.float32).reshape(shape.dims); | |||||
| var inputs = keras.Input((shape.dims[1], shape.dims[2], 3)); | |||||
| var conv2d = keras.layers.Conv2D(32, kernel_size: (3, 3), | |||||
| activation: keras.activations.Linear).Apply(inputs); | |||||
| var flatten = keras.layers.Flatten().Apply(inputs); | |||||
| var outputs = keras.layers.Dense(10).Apply(flatten); | |||||
| var model = keras.Model(inputs, outputs, "prediction"); | |||||
| for (int i = 0; i < 10; i++) | |||||
| { | |||||
| model.predict(images, batch_size: 8); | |||||
| } | |||||
| }; | |||||
| } | |||||
| } | |||||
| @@ -4,6 +4,7 @@ using System.Threading; | |||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| using NumSharp; | using NumSharp; | ||||
| using static Tensorflow.Binding; | using static Tensorflow.Binding; | ||||
| using static Tensorflow.KerasApi; | |||||
| namespace Tensorflow | namespace Tensorflow | ||||
| { | { | ||||
| @@ -11,38 +12,44 @@ namespace Tensorflow | |||||
| { | { | ||||
| public void WarmUp() | public void WarmUp() | ||||
| { | { | ||||
| TensorShape shape = (1, 32, 32, 3); | |||||
| np.arange(shape.size).astype(np.float32).reshape(shape.dims); | |||||
| print($"tensorflow native version: v{tf.VERSION}"); | print($"tensorflow native version: v{tf.VERSION}"); | ||||
| tf.Context.ensure_initialized(); | |||||
| var a = tf.constant(np.ones(10, 10)); | var a = tf.constant(np.ones(10, 10)); | ||||
| var b = tf.Variable(a); | var b = tf.Variable(a); | ||||
| var c = tf.Variable(b); | var c = tf.Variable(b); | ||||
| var d = b * c; | var d = b * c; | ||||
| print(d.numpy()); | print(d.numpy()); | ||||
| GC.WaitForPendingFinalizers(); | |||||
| GC.Collect(); | GC.Collect(); | ||||
| Thread.Sleep(1000); | |||||
| GC.WaitForPendingFinalizers(); | |||||
| } | } | ||||
| public void Execute(int epoch, int iterate, Action<int> process) | |||||
| public void Execute(int epoch, int iterate, Action<int, int> process) | |||||
| { | { | ||||
| GC.Collect(); | |||||
| GC.WaitForPendingFinalizers(); | |||||
| var initialTotalMemory = Process.GetCurrentProcess().PrivateMemorySize64; | |||||
| print($"{process.Method.Name} started..."); | print($"{process.Method.Name} started..."); | ||||
| // new thread to run | |||||
| Task.Run(() => | |||||
| for (int i = 0; i < epoch; i++) | |||||
| { | { | ||||
| for (int i = 0; i < epoch; i++) | |||||
| { | |||||
| var initialMemory = Process.GetCurrentProcess().PrivateMemorySize64;// GC.GetTotalMemory(true); | |||||
| process(iterate); | |||||
| var finalMemory = Process.GetCurrentProcess().PrivateMemorySize64; //GC.GetTotalMemory(true); | |||||
| print($"Epoch {i}: {Format(finalMemory - initialMemory)}."); | |||||
| GC.Collect(); | |||||
| GC.WaitForPendingFinalizers(); | |||||
| } | |||||
| }).Wait(); | |||||
| print($"Total {process.Method.Name} usage {Format(Process.GetCurrentProcess().PrivateMemorySize64)}"); | |||||
| var initialMemory = Process.GetCurrentProcess().PrivateMemorySize64; | |||||
| for (int j = 0; j < iterate; j++) | |||||
| process(i, j); | |||||
| keras.backend.clear_session(); | |||||
| GC.Collect(); | |||||
| GC.WaitForPendingFinalizers(); | |||||
| var finalMemory = Process.GetCurrentProcess().PrivateMemorySize64; | |||||
| print($"Epoch {i}: {Format(finalMemory - initialMemory)}."); | |||||
| } | |||||
| var finalTotalMemory = Process.GetCurrentProcess().PrivateMemorySize64; | |||||
| print($"Memory usage difference: {Format(finalTotalMemory - initialTotalMemory)} / {Format(Process.GetCurrentProcess().PrivateMemorySize64)}"); | |||||
| } | } | ||||
| private string Format(long usage) | private string Format(long usage) | ||||
| @@ -1,113 +0,0 @@ | |||||
| using NumSharp; | |||||
| using System; | |||||
| using static Tensorflow.Binding; | |||||
| namespace Tensorflow | |||||
| { | |||||
| class MemoryTestingCases | |||||
| { | |||||
| /// <summary> | |||||
| /// | |||||
| /// </summary> | |||||
| public Action<int> Constant | |||||
| => (iterate) => | |||||
| { | |||||
| for (int i = 0; i < iterate; i++) | |||||
| { | |||||
| var tensor = tf.constant(3112.0f); | |||||
| } | |||||
| }; | |||||
| public Action<int> Constant2x3 | |||||
| => (iterate) => | |||||
| { | |||||
| var nd = np.arange(1000).reshape(10, 100); | |||||
| for (int i = 0; i < iterate; i++) | |||||
| { | |||||
| var tensor = tf.constant(nd); | |||||
| var data = tensor.numpy(); | |||||
| } | |||||
| }; | |||||
| public Action<int> Variable | |||||
| => (iterate) => | |||||
| { | |||||
| for (int i = 0; i < iterate; i++) | |||||
| { | |||||
| var nd = np.arange(128 * 128 * 3).reshape(128, 128, 3); | |||||
| var variable = tf.Variable(nd); | |||||
| } | |||||
| }; | |||||
| public Action<int> MathAdd | |||||
| => (iterate) => | |||||
| { | |||||
| var x = tf.constant(3112.0f); | |||||
| var y = tf.constant(3112.0f); | |||||
| for (int i = 0; i < iterate; i++) | |||||
| { | |||||
| var z = x + y; | |||||
| } | |||||
| }; | |||||
| public Action<int> Gradient | |||||
| => (iterate) => | |||||
| { | |||||
| for (int i = 0; i < iterate; i++) | |||||
| { | |||||
| var w = tf.constant(3112.0f); | |||||
| using var tape = tf.GradientTape(); | |||||
| tape.watch(w); | |||||
| var loss = w * w; | |||||
| var grad = tape.gradient(loss, w); | |||||
| } | |||||
| }; | |||||
| public Action<int> Conv2dWithVariable | |||||
| => (iterate) => | |||||
| { | |||||
| for (int i = 0; i < iterate; i++) | |||||
| { | |||||
| var input = array_ops.zeros((10, 32, 32, 3), dtypes.float32); | |||||
| var filter = tf.Variable(array_ops.zeros((3, 3, 3, 32), dtypes.float32)); | |||||
| var strides = new[] { 1, 1, 1, 1 }; | |||||
| var dilations = new[] { 1, 1, 1, 1 }; | |||||
| var results = tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, | |||||
| "Conv2D", null, | |||||
| null, | |||||
| input, filter, | |||||
| "strides", strides, | |||||
| "use_cudnn_on_gpu", true, | |||||
| "padding", "VALID", | |||||
| "explicit_paddings", new int[0], | |||||
| "data_format", "NHWC", | |||||
| "dilations", dilations); | |||||
| } | |||||
| }; | |||||
| public Action<int> Conv2dWithTensor | |||||
| => (iterate) => | |||||
| { | |||||
| for (int i = 0; i < iterate; i++) | |||||
| { | |||||
| var input = array_ops.zeros((10, 32, 32, 3), dtypes.float32); | |||||
| var filter = array_ops.zeros((3, 3, 3, 32), dtypes.float32); | |||||
| var strides = new[] { 1, 1, 1, 1 }; | |||||
| var dilations = new[] { 1, 1, 1, 1 }; | |||||
| var results = tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, | |||||
| "Conv2D", null, | |||||
| null, | |||||
| input, filter, | |||||
| "strides", strides, | |||||
| "use_cudnn_on_gpu", true, | |||||
| "padding", "VALID", | |||||
| "explicit_paddings", new int[0], | |||||
| "data_format", "NHWC", | |||||
| "dilations", dilations); | |||||
| } | |||||
| }; | |||||
| } | |||||
| } | |||||
| @@ -1,4 +1,5 @@ | |||||
| using System; | using System; | ||||
| using static Tensorflow.Binding; | |||||
| namespace Tensorflow | namespace Tensorflow | ||||
| { | { | ||||
| @@ -6,6 +7,9 @@ namespace Tensorflow | |||||
| { | { | ||||
| static void Main(string[] args) | static void Main(string[] args) | ||||
| { | { | ||||
| var diag = new Diagnostician(); | |||||
| // diag.Diagnose(@"D:\memory.txt"); | |||||
| // this class is used explor new features. | // this class is used explor new features. | ||||
| var exploring = new Exploring(); | var exploring = new Exploring(); | ||||
| // exploring.Run(); | // exploring.Run(); | ||||
| @@ -14,34 +18,72 @@ namespace Tensorflow | |||||
| var mm = new MemoryMonitor(); | var mm = new MemoryMonitor(); | ||||
| // warm up tensorflow.net 37.3M. | // warm up tensorflow.net 37.3M. | ||||
| mm.WarmUp(); | mm.WarmUp(); | ||||
| var cases = new MemoryTestingCases(); | |||||
| BasicTest(mm); | |||||
| KerasTest(mm); | |||||
| FuncGraph(mm); | |||||
| // 85M | |||||
| Console.WriteLine("Finished."); | |||||
| Console.ReadLine(); | |||||
| } | |||||
| static void BasicTest(MemoryMonitor mm) | |||||
| { | |||||
| int batchSize = 1000; | int batchSize = 1000; | ||||
| var basic = new MemoryBasicTest(); | |||||
| // 1 million placeholder | |||||
| /*tf.compat.v1.disable_eager_execution(); | |||||
| mm.Execute(10, 100 * batchSize, basic.Placeholder); | |||||
| tf.enable_eager_execution();*/ | |||||
| // 1 million tensor | // 1 million tensor | ||||
| mm.Execute(10, 100 * batchSize, cases.Constant); | |||||
| mm.Execute(10, 100 * batchSize, basic.Constant); | |||||
| // explaination of constant | // explaination of constant | ||||
| mm.Execute(10, 100 * batchSize, cases.Constant2x3); | |||||
| mm.Execute(10, 100 * batchSize, basic.Constant2x3); | |||||
| mm.Execute(10, 100 * batchSize, basic.ConstantString); | |||||
| // +0M | |||||
| mm.Execute(10, batchSize, cases.Conv2dWithTensor); | |||||
| // 100K float variable. | |||||
| mm.Execute(10, batchSize, basic.Variable); | |||||
| // 100K float variable 84M. | |||||
| mm.Execute(10, batchSize, cases.Variable); | |||||
| // 1 million math. | |||||
| mm.Execute(10, 100 * batchSize, basic.MathAdd); | |||||
| // +45M memory leak | |||||
| mm.Execute(10, batchSize, cases.Conv2dWithVariable); | |||||
| // Conv2d in constant tensor | |||||
| mm.Execute(10, batchSize, basic.Conv2DWithTensor); | |||||
| // 1 million math add 39M. | |||||
| mm.Execute(10, 100 * batchSize, cases.MathAdd); | |||||
| // Conv2d in variable | |||||
| mm.Execute(10, batchSize, basic.Conv2DWithVariable); | |||||
| // 100K gradient 44M. | // 100K gradient 44M. | ||||
| mm.Execute(10, 10 * batchSize, cases.Gradient); | |||||
| mm.Execute(10, 10 * batchSize, basic.Gradient); | |||||
| // 95M | |||||
| Console.WriteLine("Finished."); | |||||
| Console.ReadLine(); | |||||
| // memory leak when increasing the epoch | |||||
| mm.Execute(10, 10, basic.Dataset); | |||||
| } | |||||
| static void KerasTest(MemoryMonitor mm) | |||||
| { | |||||
| var keras = new MemoryKerasTest(); | |||||
| // +1M (10,50) | |||||
| mm.Execute(10, 1, keras.Conv2DLayer); | |||||
| mm.Execute(10, 50, keras.InputLayer); | |||||
| mm.Execute(10, 10, keras.Prediction); | |||||
| } | |||||
| static void FuncGraph(MemoryMonitor mm) | |||||
| { | |||||
| var func = new MemoryFuncGraphTest(); | |||||
| mm.Execute(10, 100, func.ConcreteFunction); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -6,6 +6,7 @@ | |||||
| <RootNamespace>Tensorflow</RootNamespace> | <RootNamespace>Tensorflow</RootNamespace> | ||||
| <AssemblyName>Tensorflow</AssemblyName> | <AssemblyName>Tensorflow</AssemblyName> | ||||
| <Platforms>AnyCPU;x64</Platforms> | <Platforms>AnyCPU;x64</Platforms> | ||||
| <LangVersion>9.0</LangVersion> | |||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | ||||
| @@ -4,7 +4,6 @@ namespace Tensorflow | |||||
| { | { | ||||
| public static partial class Binding | public static partial class Binding | ||||
| { | { | ||||
| [DebuggerHidden] | |||||
| public static tensorflow tf { get; } = New<tensorflow>(); | public static tensorflow tf { get; } = New<tensorflow>(); | ||||
| /// <summary> | /// <summary> | ||||
| @@ -81,7 +81,7 @@ namespace Tensorflow.Contexts | |||||
| /// Checks whether the current thread has eager execution enabled. | /// Checks whether the current thread has eager execution enabled. | ||||
| /// </summary> | /// </summary> | ||||
| /// <returns></returns> | /// <returns></returns> | ||||
| // [DebuggerStepThrough] | |||||
| [DebuggerStepThrough] | |||||
| public bool executing_eagerly() | public bool executing_eagerly() | ||||
| { | { | ||||
| if(context_switches.Count() == 0) | if(context_switches.Count() == 0) | ||||
| @@ -136,8 +136,11 @@ namespace Tensorflow.Contexts | |||||
| public void reset_context() | public void reset_context() | ||||
| { | { | ||||
| ops.reset_uid(); | ops.reset_uid(); | ||||
| // tf.defaultSession = null; | |||||
| ops.reset_default_graph(); | ops.reset_default_graph(); | ||||
| context_switches.Clear(); | context_switches.Clear(); | ||||
| tf.Context.ensure_initialized(); | |||||
| if (_handle != null) | if (_handle != null) | ||||
| c_api.TFE_ContextClearCaches(_handle); | c_api.TFE_ContextClearCaches(_handle); | ||||
| } | } | ||||
| @@ -1,6 +0,0 @@ | |||||
| namespace Tensorflow | |||||
| { | |||||
| public class IteratorBase | |||||
| { | |||||
| } | |||||
| } | |||||
| @@ -1,26 +0,0 @@ | |||||
| using System; | |||||
| namespace Tensorflow | |||||
| { | |||||
| /// <summary> | |||||
| /// An object which cleans up an iterator resource handle. | |||||
| /// </summary> | |||||
| public class IteratorResourceDeleter : IDisposable | |||||
| { | |||||
| Tensor _handle; | |||||
| Tensor _deleter; | |||||
| dataset_ops ops; | |||||
| public IteratorResourceDeleter(Tensor handle, Tensor deleter) | |||||
| { | |||||
| _handle = handle; | |||||
| _deleter = deleter; | |||||
| ops = new dataset_ops(); | |||||
| } | |||||
| public void Dispose() | |||||
| { | |||||
| ops.delete_iterator(_handle, _deleter); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -15,7 +15,7 @@ namespace Tensorflow | |||||
| bool preserve_cardinality = false, | bool preserve_cardinality = false, | ||||
| bool use_legacy_function = false) : base(input_dataset) | bool use_legacy_function = false) : base(input_dataset) | ||||
| { | { | ||||
| using var func = new ConcreteFunction($"{map_func.Method.Name}_{Guid.NewGuid()}"); | |||||
| var func = new ConcreteFunction($"{map_func.Method.Name}_{Guid.NewGuid()}"); | |||||
| func.Enter(); | func.Enter(); | ||||
| var input = tf.placeholder(input_dataset.element_spec[0].dtype); | var input = tf.placeholder(input_dataset.element_spec[0].dtype); | ||||
| var output = map_func(input); | var output = map_func(input); | ||||
| @@ -7,8 +7,6 @@ namespace Tensorflow | |||||
| /// </summary> | /// </summary> | ||||
| public class OptimizeDataset : UnaryUnchangedStructureDataset | public class OptimizeDataset : UnaryUnchangedStructureDataset | ||||
| { | { | ||||
| Tensor _optimizations; | |||||
| public OptimizeDataset(IDatasetV2 dataset, | public OptimizeDataset(IDatasetV2 dataset, | ||||
| string[] optimizations = null, | string[] optimizations = null, | ||||
| string[] optimization_configs = null) : | string[] optimization_configs = null) : | ||||
| @@ -19,7 +17,7 @@ namespace Tensorflow | |||||
| if (optimization_configs == null) | if (optimization_configs == null) | ||||
| optimization_configs = new string[0]; | optimization_configs = new string[0]; | ||||
| _optimizations = tf.convert_to_tensor(optimizations, dtype: TF_DataType.TF_STRING, name: "optimizations"); | |||||
| var _optimizations = tf.convert_to_tensor(optimizations, dtype: TF_DataType.TF_STRING, name: "optimizations"); | |||||
| variant_tensor = ops.optimize_dataset( | variant_tensor = ops.optimize_dataset( | ||||
| _input_dataset.variant_tensor, | _input_dataset.variant_tensor, | ||||
| _optimizations, | _optimizations, | ||||
| @@ -8,14 +8,13 @@ namespace Tensorflow | |||||
| /// <summary> | /// <summary> | ||||
| /// An iterator producing tf.Tensor objects from a tf.data.Dataset. | /// An iterator producing tf.Tensor objects from a tf.data.Dataset. | ||||
| /// </summary> | /// </summary> | ||||
| public class OwnedIterator : IteratorBase, IDisposable | |||||
| public class OwnedIterator : IDisposable | |||||
| { | { | ||||
| IDatasetV2 _dataset; | IDatasetV2 _dataset; | ||||
| TensorSpec[] _element_spec; | TensorSpec[] _element_spec; | ||||
| dataset_ops ops = new dataset_ops(); | dataset_ops ops = new dataset_ops(); | ||||
| Tensor _iterator_resource; | |||||
| Tensor _deleter; | Tensor _deleter; | ||||
| IteratorResourceDeleter _resource_deleter; | |||||
| Tensor _iterator_resource; | |||||
| public OwnedIterator(IDatasetV2 dataset) | public OwnedIterator(IDatasetV2 dataset) | ||||
| { | { | ||||
| @@ -29,9 +28,6 @@ namespace Tensorflow | |||||
| _element_spec = dataset.element_spec; | _element_spec = dataset.element_spec; | ||||
| (_iterator_resource, _deleter) = ops.anonymous_iterator_v2(_dataset.output_types, _dataset.output_shapes); | (_iterator_resource, _deleter) = ops.anonymous_iterator_v2(_dataset.output_types, _dataset.output_shapes); | ||||
| ops.make_iterator(dataset.variant_tensor, _iterator_resource); | ops.make_iterator(dataset.variant_tensor, _iterator_resource); | ||||
| // Delete the resource when this object is deleted | |||||
| _resource_deleter = new IteratorResourceDeleter(_iterator_resource, _deleter); | |||||
| } | } | ||||
| public Tensor[] next() | public Tensor[] next() | ||||
| @@ -51,7 +47,7 @@ namespace Tensorflow | |||||
| public void Dispose() | public void Dispose() | ||||
| { | { | ||||
| _resource_deleter.Dispose(); | |||||
| tf.Runner.Execute(tf.Context, "DeleteIterator", 0, new[] { _iterator_resource, _deleter }, null); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -7,17 +7,15 @@ namespace Tensorflow | |||||
| /// </summary> | /// </summary> | ||||
| public class PrefetchDataset : UnaryUnchangedStructureDataset | public class PrefetchDataset : UnaryUnchangedStructureDataset | ||||
| { | { | ||||
| Tensor _buffer_size; | |||||
| public PrefetchDataset(IDatasetV2 input_dataset, | public PrefetchDataset(IDatasetV2 input_dataset, | ||||
| long buffer_size = -1, | long buffer_size = -1, | ||||
| int? slack_period = null) : | int? slack_period = null) : | ||||
| base(input_dataset) | base(input_dataset) | ||||
| { | { | ||||
| _buffer_size = tf.convert_to_tensor(buffer_size, dtype: TF_DataType.TF_INT64, name: "buffer_size"); | |||||
| var buffer_size_tensor = tf.convert_to_tensor(buffer_size, dtype: TF_DataType.TF_INT64, name: "buffer_size"); | |||||
| variant_tensor = ops.prefetch_dataset(input_dataset.variant_tensor, | variant_tensor = ops.prefetch_dataset(input_dataset.variant_tensor, | ||||
| _buffer_size, | |||||
| buffer_size_tensor, | |||||
| input_dataset.output_types, | input_dataset.output_types, | ||||
| input_dataset.output_shapes, | input_dataset.output_shapes, | ||||
| slack_period: slack_period); | slack_period: slack_period); | ||||
| @@ -5,21 +5,17 @@ namespace Tensorflow.Data | |||||
| { | { | ||||
| public class RangeDataset : DatasetSource | public class RangeDataset : DatasetSource | ||||
| { | { | ||||
| Tensor start; | |||||
| Tensor step; | |||||
| Tensor stop; | |||||
| public RangeDataset(int stop, | public RangeDataset(int stop, | ||||
| int start = 0, | int start = 0, | ||||
| int step = 1, | int step = 1, | ||||
| TF_DataType output_type = TF_DataType.TF_INT64) | TF_DataType output_type = TF_DataType.TF_INT64) | ||||
| { | { | ||||
| this.start = tf.convert_to_tensor((long)start); | |||||
| this.step = tf.convert_to_tensor((long)step); | |||||
| this.stop = tf.convert_to_tensor((long)stop); | |||||
| var start_tensor = tf.convert_to_tensor((long)start); | |||||
| var step_tensor = tf.convert_to_tensor((long)step); | |||||
| var stop_tensor = tf.convert_to_tensor((long)stop); | |||||
| structure = new TensorSpec[] { new TensorSpec(new int[0], dtype: output_type) }; | structure = new TensorSpec[] { new TensorSpec(new int[0], dtype: output_type) }; | ||||
| variant_tensor = ops.range_dataset(this.start, this.stop, this.step, output_types, output_shapes); | |||||
| variant_tensor = ops.range_dataset(start_tensor, stop_tensor, step_tensor, output_types, output_shapes); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -5,14 +5,12 @@ | |||||
| /// </summary> | /// </summary> | ||||
| public class RepeatDataset : UnaryUnchangedStructureDataset | public class RepeatDataset : UnaryUnchangedStructureDataset | ||||
| { | { | ||||
| Tensor _count; | |||||
| public RepeatDataset(IDatasetV2 input_dataset, int count = -1) : | public RepeatDataset(IDatasetV2 input_dataset, int count = -1) : | ||||
| base(input_dataset) | base(input_dataset) | ||||
| { | { | ||||
| _count = constant_op.constant(count, dtype: TF_DataType.TF_INT64, name: "count"); | |||||
| var count_tensor = constant_op.constant(count, dtype: TF_DataType.TF_INT64, name: "count"); | |||||
| variant_tensor = ops.repeat_dataset(input_dataset.variant_tensor, | variant_tensor = ops.repeat_dataset(input_dataset.variant_tensor, | ||||
| _count, | |||||
| count_tensor, | |||||
| input_dataset.output_types, | input_dataset.output_types, | ||||
| input_dataset.output_shapes); | input_dataset.output_shapes); | ||||
| } | } | ||||
| @@ -42,8 +42,7 @@ namespace Tensorflow.Eager | |||||
| int num_outputs) | int num_outputs) | ||||
| { | { | ||||
| var status = tf.Status; | var status = tf.Status; | ||||
| var op = GetOp(ctx, op_name, status); | |||||
| status.Check(true); | |||||
| using var op = GetOp(ctx, op_name, status); | |||||
| c_api.TFE_OpSetDevice(op, device_name, status.Handle); | c_api.TFE_OpSetDevice(op, device_name, status.Handle); | ||||
| if (status.ok()) | if (status.ok()) | ||||
| { | { | ||||
| @@ -67,7 +66,7 @@ namespace Tensorflow.Eager | |||||
| c_api.TFE_Execute(op, outputs, out num_outputs, status.Handle); | c_api.TFE_Execute(op, outputs, out num_outputs, status.Handle); | ||||
| status.Check(true); | status.Check(true); | ||||
| } | } | ||||
| return outputs.Select(x => new EagerTensor(x, op)).ToArray(); | |||||
| return outputs.Select(x => new EagerTensor(x)).ToArray(); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -46,7 +46,7 @@ namespace Tensorflow.Eager | |||||
| op_exec_info.run_callbacks = op_exec_info.run_gradient_callback || op_exec_info.run_post_exec_callbacks; | op_exec_info.run_callbacks = op_exec_info.run_gradient_callback || op_exec_info.run_post_exec_callbacks; | ||||
| var status = tf.Status; | var status = tf.Status; | ||||
| var op = GetOp(ctx, opName, status); | |||||
| using var op = GetOp(ctx, opName, status); | |||||
| var op_def = tf.get_default_graph().GetOpDef(opName); | var op_def = tf.get_default_graph().GetOpDef(opName); | ||||
| @@ -158,7 +158,8 @@ namespace Tensorflow.Eager | |||||
| c_api.TFE_Execute(op, retVals, out num_retvals, status.Handle); | c_api.TFE_Execute(op, retVals, out num_retvals, status.Handle); | ||||
| status.Check(true); | status.Check(true); | ||||
| var flat_result = retVals.Select(x => new EagerTensor(x, op)).ToArray(); | |||||
| var flat_result = retVals.Select(x => new EagerTensor(x)).ToArray(); | |||||
| if (op_exec_info.run_callbacks) | if (op_exec_info.run_callbacks) | ||||
| { | { | ||||
| @@ -183,9 +184,7 @@ namespace Tensorflow.Eager | |||||
| status.Check(true); | status.Check(true); | ||||
| return op;*/ | return op;*/ | ||||
| var op = c_api.TFE_NewOp(ctx.Handle, op_or_function_name, status.Handle); | var op = c_api.TFE_NewOp(ctx.Handle, op_or_function_name, status.Handle); | ||||
| #if TRACK_TENSOR_LIFE | |||||
| print($"New OpHandle 0x{op.DangerousGetHandle().ToString("x16")}"); | |||||
| #endif | |||||
| status.Check(true); | |||||
| return op; | return op; | ||||
| } | } | ||||
| @@ -1,57 +1,56 @@ | |||||
| using NumSharp; | using NumSharp; | ||||
| using System; | using System; | ||||
| using System.Linq; | |||||
| using static Tensorflow.Binding; | using static Tensorflow.Binding; | ||||
| namespace Tensorflow.Eager | namespace Tensorflow.Eager | ||||
| { | { | ||||
| public partial class EagerTensor | public partial class EagerTensor | ||||
| { | { | ||||
| SafeOpHandle _opHandle; | |||||
| public EagerTensor(SafeTensorHandleHandle handle, SafeOpHandle opHandle) : base(IntPtr.Zero) | |||||
| public EagerTensor(SafeTensorHandleHandle handle) : base(IntPtr.Zero) | |||||
| { | { | ||||
| _opHandle = opHandle; | |||||
| _id = ops.uid(); | |||||
| EagerTensorHandle = handle; | EagerTensorHandle = handle; | ||||
| Resolve(); | Resolve(); | ||||
| } | } | ||||
| public EagerTensor(string value, string device_name) : base(value) | public EagerTensor(string value, string device_name) : base(value) | ||||
| { | { | ||||
| SetEagerTensorHandleAndResolve(); | |||||
| NewEagerTensorHandle(_handle); | |||||
| } | } | ||||
| public EagerTensor(byte[] value, string device_name, TF_DataType dtype) : base(value, dType: dtype) | public EagerTensor(byte[] value, string device_name, TF_DataType dtype) : base(value, dType: dtype) | ||||
| { | { | ||||
| SetEagerTensorHandleAndResolve(); | |||||
| NewEagerTensorHandle(_handle); | |||||
| } | } | ||||
| public EagerTensor(string[] value, string device_name) : base(value) | public EagerTensor(string[] value, string device_name) : base(value) | ||||
| { | { | ||||
| SetEagerTensorHandleAndResolve(); | |||||
| NewEagerTensorHandle(_handle); | |||||
| } | } | ||||
| public EagerTensor(NDArray value, string device_name) : base(value) | public EagerTensor(NDArray value, string device_name) : base(value) | ||||
| { | { | ||||
| SetEagerTensorHandleAndResolve(); | |||||
| NewEagerTensorHandle(_handle); | |||||
| } | } | ||||
| void SetEagerTensorHandleAndResolve() | |||||
| void NewEagerTensorHandle(IntPtr h) | |||||
| { | { | ||||
| EagerTensorHandle = c_api.TFE_NewTensorHandle(_handle, tf.Status.Handle); | |||||
| Resolve(); | |||||
| _id = ops.uid(); | |||||
| EagerTensorHandle = c_api.TFE_NewTensorHandle(h, tf.Status.Handle); | |||||
| tf.Status.Check(true); | |||||
| #if TRACK_TENSOR_LIFE | |||||
| print($"New EagerTensorHandle {EagerTensorHandle} {Id} From 0x{h.ToString("x16")}"); | |||||
| #endif | |||||
| } | } | ||||
| public EagerTensor Resolve() | |||||
| private void Resolve() | |||||
| { | { | ||||
| _id = ops.uid(); | |||||
| if (_handle == IntPtr.Zero) | |||||
| _handle = c_api.TFE_TensorHandleResolve(EagerTensorHandle, tf.Status.Handle); | |||||
| _handle = c_api.TFE_TensorHandleResolve(EagerTensorHandle, tf.Status.Handle); | |||||
| tf.Status.Check(true); | |||||
| #if TRACK_TENSOR_LIFE | #if TRACK_TENSOR_LIFE | ||||
| print($"New TensorHandle {Id} 0x{_handle.ToString("x16")}"); | |||||
| print($"New EagerTensorHandle {Id} {EagerTensorHandle}"); | |||||
| print($"Take EagerTensorHandle {EagerTensorHandle} {Id} Resolving 0x{_handle.ToString("x16")}"); | |||||
| #endif | #endif | ||||
| return this; | |||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| @@ -80,22 +79,10 @@ namespace Tensorflow.Eager | |||||
| } | } | ||||
| } | } | ||||
| public override IntPtr ToPointer() | |||||
| => EagerTensorHandle?.DangerousGetHandle() ?? IntPtr.Zero; | |||||
| protected override void DisposeManagedResources() | |||||
| { | |||||
| base.DisposeManagedResources(); | |||||
| } | |||||
| protected override void DisposeUnmanagedResources(IntPtr handle) | protected override void DisposeUnmanagedResources(IntPtr handle) | ||||
| { | { | ||||
| base.DisposeUnmanagedResources(handle); | base.DisposeUnmanagedResources(handle); | ||||
| EagerTensorHandle.Dispose(); | EagerTensorHandle.Dispose(); | ||||
| if (_opHandle != null) | |||||
| _opHandle.Dispose(); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -4,8 +4,7 @@ namespace Tensorflow.Eager | |||||
| { | { | ||||
| public partial class EagerTensor | public partial class EagerTensor | ||||
| { | { | ||||
| [Obsolete("Implicit conversion of EagerTensor to IntPtr is not supported.", error: true)] | |||||
| public static implicit operator IntPtr(EagerTensor tensor) | public static implicit operator IntPtr(EagerTensor tensor) | ||||
| => throw new NotSupportedException(); | |||||
| => tensor.EagerTensorHandle.DangerousGetHandle(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -30,16 +30,11 @@ namespace Tensorflow.Eager | |||||
| public SafeOpHandle(IntPtr handle) | public SafeOpHandle(IntPtr handle) | ||||
| : base(handle) | : base(handle) | ||||
| { | { | ||||
| #if TRACK_TENSOR_LIFE | |||||
| print($"Get OpHandle 0x{handle.ToString("x16")}"); | |||||
| #endif | |||||
| } | } | ||||
| protected override bool ReleaseHandle() | protected override bool ReleaseHandle() | ||||
| { | { | ||||
| #if TRACK_TENSOR_LIFE | |||||
| print($"Delete OpHandle 0x{handle.ToString("x16")}"); | |||||
| #endif | |||||
| c_api.TFE_DeleteOp(handle); | c_api.TFE_DeleteOp(handle); | ||||
| SetHandle(IntPtr.Zero); | SetHandle(IntPtr.Zero); | ||||
| return true; | return true; | ||||
| @@ -10,24 +10,14 @@ namespace Tensorflow.Functions | |||||
| /// <summary> | /// <summary> | ||||
| /// | /// | ||||
| /// </summary> | /// </summary> | ||||
| public class ConcreteFunction : IDisposable | |||||
| public class ConcreteFunction | |||||
| { | { | ||||
| IntPtr _handle; | |||||
| FuncGraph func_graph; | FuncGraph func_graph; | ||||
| public Tensor[] Inputs => func_graph.Inputs; | public Tensor[] Inputs => func_graph.Inputs; | ||||
| public Tensor[] CapturedInputs => func_graph.external_captures; | public Tensor[] CapturedInputs => func_graph.external_captures; | ||||
| public string Name | |||||
| { | |||||
| get | |||||
| { | |||||
| if (func_graph != null) | |||||
| return func_graph.FuncName; | |||||
| public string Name => func_graph?.FuncName; | |||||
| return _handle == IntPtr.Zero ? string.Empty : c_api.StringPiece(c_api.TF_FunctionName(_handle)); | |||||
| } | |||||
| } | |||||
| public Tensor[] Outputs; | public Tensor[] Outputs; | ||||
| public Type ReturnType; | public Type ReturnType; | ||||
| public TensorSpec[] OutputStructure; | public TensorSpec[] OutputStructure; | ||||
| @@ -48,39 +38,37 @@ namespace Tensorflow.Functions | |||||
| { | { | ||||
| string func_name = $"{func.Method.Name}_{Guid.NewGuid()}"; | string func_name = $"{func.Method.Name}_{Guid.NewGuid()}"; | ||||
| // IntPtr func_handle; | |||||
| using var graph = new FuncGraph(func_name); | |||||
| graph.as_default(); | |||||
| func_graph = new FuncGraph(func_name); | |||||
| func_graph.as_default(); | |||||
| var input = tf.placeholder(dtype); | var input = tf.placeholder(dtype); | ||||
| var output = func(input); | var output = func(input); | ||||
| var opers = graph._nodes_by_name.Values.Select(x => x as Operation).ToArray(); | |||||
| _handle = graph.ToGraph(opers, | |||||
| var opers = func_graph._nodes_by_name.Values.Select(x => x as Operation).ToArray(); | |||||
| func_graph.ToGraph(opers, | |||||
| new[] { input }, | new[] { input }, | ||||
| new[] { output }, | new[] { output }, | ||||
| null); | null); | ||||
| graph.Exit(); | |||||
| func_graph.Exit(); | |||||
| } | } | ||||
| public ConcreteFunction(Func<Tensor, IDatasetV2> func, TF_DataType dtype) | public ConcreteFunction(Func<Tensor, IDatasetV2> func, TF_DataType dtype) | ||||
| { | { | ||||
| string func_name = $"{func.Method.Name}_{Guid.NewGuid()}"; | string func_name = $"{func.Method.Name}_{Guid.NewGuid()}"; | ||||
| // IntPtr func_handle; | |||||
| using var graph = new FuncGraph(func_name); | |||||
| graph.as_default(); | |||||
| func_graph = new FuncGraph(func_name); | |||||
| func_graph.as_default(); | |||||
| var input = tf.placeholder(dtype); | var input = tf.placeholder(dtype); | ||||
| var output = func(input); | var output = func(input); | ||||
| OutputStructure = output.structure; | OutputStructure = output.structure; | ||||
| var opers = graph._nodes_by_name.Values.Select(x => x as Operation).ToArray(); | |||||
| _handle = graph.ToGraph(opers, | |||||
| var opers = func_graph._nodes_by_name.Values.Select(x => x as Operation).ToArray(); | |||||
| func_graph.ToGraph(opers, | |||||
| new[] { input }, | new[] { input }, | ||||
| new[] { output.variant_tensor }, | new[] { output.variant_tensor }, | ||||
| null); | null); | ||||
| graph.Exit(); | |||||
| func_graph.Exit(); | |||||
| } | } | ||||
| public ConcreteFunction(Func<Tensors, Tensors> func, | public ConcreteFunction(Func<Tensors, Tensors> func, | ||||
| @@ -89,8 +77,8 @@ namespace Tensorflow.Functions | |||||
| string func_name = $"{func.Method.Name}_{Guid.NewGuid()}"; | string func_name = $"{func.Method.Name}_{Guid.NewGuid()}"; | ||||
| // IntPtr func_handle; | // IntPtr func_handle; | ||||
| using var graph = new FuncGraph(func_name); | |||||
| graph.as_default(); | |||||
| func_graph = new FuncGraph(func_name); | |||||
| func_graph.as_default(); | |||||
| var inputs = new Tensors(); | var inputs = new Tensors(); | ||||
| foreach(var (i, dtype) in enumerate(dtypes)) | foreach(var (i, dtype) in enumerate(dtypes)) | ||||
| @@ -98,15 +86,15 @@ namespace Tensorflow.Functions | |||||
| Outputs = func(inputs); | Outputs = func(inputs); | ||||
| OutputStructure = Outputs.Select(x => x.ToTensorSpec()).ToArray(); | OutputStructure = Outputs.Select(x => x.ToTensorSpec()).ToArray(); | ||||
| var opers = graph._nodes_by_name.Values.Select(x => x as Operation).ToArray(); | |||||
| _handle = graph.ToGraph(opers, inputs, Outputs, null); | |||||
| graph.Exit(); | |||||
| var opers = func_graph._nodes_by_name.Values.Select(x => x as Operation).ToArray(); | |||||
| func_graph.ToGraph(opers, inputs, Outputs, null); | |||||
| func_graph.Exit(); | |||||
| } | } | ||||
| public void ToGraph(Tensors inputs, Tensors outputs) | public void ToGraph(Tensors inputs, Tensors outputs) | ||||
| { | { | ||||
| var opers = func_graph._nodes_by_name.Values.Select(x => x as Operation).ToArray(); | var opers = func_graph._nodes_by_name.Values.Select(x => x as Operation).ToArray(); | ||||
| _handle = func_graph.ToGraph(opers, | |||||
| func_graph.ToGraph(opers, | |||||
| inputs, | inputs, | ||||
| outputs, | outputs, | ||||
| null); | null); | ||||
| @@ -180,11 +168,5 @@ namespace Tensorflow.Functions | |||||
| public override string ToString() | public override string ToString() | ||||
| => Name; | => Name; | ||||
| public void Dispose() | |||||
| { | |||||
| c_api.TFE_ContextRemoveFunction(tf.Context.Handle, Name, tf.Status.Handle); | |||||
| c_api.TF_DeleteFunction(_handle); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -10,20 +10,18 @@ namespace Tensorflow.Graphs | |||||
| { | { | ||||
| string func_name = $"{func.Method.Name}_{Guid.NewGuid()}"; | string func_name = $"{func.Method.Name}_{Guid.NewGuid()}"; | ||||
| // IntPtr func_handle; | |||||
| using (var graph = new FuncGraph(func_name)) | |||||
| { | |||||
| graph.as_default(); | |||||
| var input = tf.placeholder(tf.int32); | |||||
| var output = func(input); | |||||
| var graph = new FuncGraph(func_name); | |||||
| graph.as_default(); | |||||
| var opers = graph._nodes_by_name.Values.Select(x => x as Operation).ToArray(); | |||||
| var func_handle = graph.ToGraph(opers, | |||||
| new[] { input }, | |||||
| new[] { output }, | |||||
| null); | |||||
| graph.Exit(); | |||||
| } | |||||
| var input = tf.placeholder(tf.int32); | |||||
| var output = func(input); | |||||
| var opers = graph._nodes_by_name.Values.Select(x => x as Operation).ToArray(); | |||||
| graph.ToGraph(opers, | |||||
| new[] { input }, | |||||
| new[] { output }, | |||||
| null); | |||||
| graph.Exit(); | |||||
| return (Tensor input) => | return (Tensor input) => | ||||
| @@ -42,21 +40,19 @@ namespace Tensorflow.Graphs | |||||
| { | { | ||||
| string func_name = $"{func.Method.Name}_{Guid.NewGuid()}"; | string func_name = $"{func.Method.Name}_{Guid.NewGuid()}"; | ||||
| // IntPtr func_handle; | |||||
| using (var graph = new FuncGraph(func_name)) | |||||
| { | |||||
| graph.as_default(); | |||||
| var input1 = tf.placeholder(tf.int32); | |||||
| var input2 = tf.placeholder(tf.int32); | |||||
| var output = func(input1, input2); | |||||
| var graph = new FuncGraph(func_name); | |||||
| graph.as_default(); | |||||
| var input1 = tf.placeholder(tf.int32); | |||||
| var input2 = tf.placeholder(tf.int32); | |||||
| var output = func(input1, input2); | |||||
| var opers = graph._nodes_by_name.Values.Select(x => x as Operation).ToArray(); | |||||
| var func_handle = graph.ToGraph(opers, | |||||
| new[] { input1, input2 }, | |||||
| new[] { output }, | |||||
| null); | |||||
| graph.Exit(); | |||||
| } | |||||
| var opers = graph._nodes_by_name.Values.Select(x => x as Operation).ToArray(); | |||||
| graph.ToGraph(opers, | |||||
| new[] { input1, input2 }, | |||||
| new[] { output }, | |||||
| null); | |||||
| graph.Exit(); | |||||
| return (Tensor a, Tensor b) => | return (Tensor a, Tensor b) => | ||||
| { | { | ||||
| @@ -13,8 +13,7 @@ namespace Tensorflow.Graphs | |||||
| /// </summary> | /// </summary> | ||||
| public class FuncGraph : Graph | public class FuncGraph : Graph | ||||
| { | { | ||||
| // _handle == IntPtr.Zero ? string.Empty : c_api.StringPiece(c_api.TF_FunctionName(_handle)); | |||||
| IntPtr func_handle; | |||||
| IntPtr _func_graph_handle; | |||||
| public string FuncName => _graph_key; | public string FuncName => _graph_key; | ||||
| public Tensors Inputs { get; set; } = new Tensors(); | public Tensors Inputs { get; set; } = new Tensors(); | ||||
| @@ -60,12 +59,12 @@ namespace Tensorflow.Graphs | |||||
| _handle = handle; | _handle = handle; | ||||
| } | } | ||||
| public IntPtr ToGraph(Operation[] opers, | |||||
| public void ToGraph(Operation[] opers, | |||||
| Tensor[] inputs, Tensor[] outputs, | Tensor[] inputs, Tensor[] outputs, | ||||
| string[] output_names) | string[] output_names) | ||||
| { | { | ||||
| using var status = new Status(); | |||||
| func_handle = c_api.TF_GraphToFunction(_handle, | |||||
| var status = new Status(); | |||||
| _func_graph_handle = c_api.TF_GraphToFunction(_handle, | |||||
| _graph_key, | _graph_key, | ||||
| false, | false, | ||||
| opers.Length, | opers.Length, | ||||
| @@ -82,19 +81,17 @@ namespace Tensorflow.Graphs | |||||
| SetAttrs(); | SetAttrs(); | ||||
| c_api.TF_GraphCopyFunction(outer_graph, func_handle, IntPtr.Zero, status.Handle); | |||||
| status.Check(true); | |||||
| // c_api.TF_GraphCopyFunction(outer_graph, _func_graph_handle, IntPtr.Zero, status.Handle); | |||||
| // status.Check(true); | |||||
| c_api.TFE_ContextAddFunction(tf.Context.Handle, func_handle, status.Handle); | |||||
| c_api.TFE_ContextAddFunction(tf.Context.Handle, _func_graph_handle, status.Handle); | |||||
| status.Check(true); | status.Check(true); | ||||
| _graph_key = c_api.StringPiece(c_api.TF_FunctionName(func_handle)); | |||||
| _graph_key = c_api.StringPiece(c_api.TF_FunctionName(_func_graph_handle)); | |||||
| Inputs = inputs; | Inputs = inputs; | ||||
| // mark_as_return | // mark_as_return | ||||
| Outputs = outputs;// .Select(x => array_ops.identity(x)).ToArray(); | Outputs = outputs;// .Select(x => array_ops.identity(x)).ToArray(); | ||||
| return func_handle; | |||||
| } | } | ||||
| public override Operation create_op(string op_type, Tensor[] inputs, TF_DataType[] dtypes, TF_DataType[] input_types = null, string name = null, Dictionary<string, AttrValue> attrs = null, OpDef op_def = null, bool compute_device = true) | public override Operation create_op(string op_type, Tensor[] inputs, TF_DataType[] dtypes, TF_DataType[] input_types = null, string name = null, Dictionary<string, AttrValue> attrs = null, OpDef op_def = null, bool compute_device = true) | ||||
| @@ -233,7 +230,7 @@ namespace Tensorflow.Graphs | |||||
| { | { | ||||
| S = ByteString.CopyFromUtf8(attr_value) | S = ByteString.CopyFromUtf8(attr_value) | ||||
| }.ToByteArray(); | }.ToByteArray(); | ||||
| c_api.TF_FunctionSetAttrValueProto(func_handle, _name, serialized, serialized.Length, tf.Status.Handle); | |||||
| c_api.TF_FunctionSetAttrValueProto(_func_graph_handle, _name, serialized, serialized.Length, tf.Status.Handle); | |||||
| tf.Status.Check(true); | tf.Status.Check(true); | ||||
| } | } | ||||
| } | } | ||||
| @@ -250,5 +247,12 @@ namespace Tensorflow.Graphs | |||||
| tf.Context.restore_mode(); | tf.Context.restore_mode(); | ||||
| ops.pop_graph(); | ops.pop_graph(); | ||||
| } | } | ||||
| protected override void DisposeUnmanagedResources(IntPtr handle) | |||||
| { | |||||
| c_api.TFE_ContextRemoveFunction(tf.Context.Handle, _graph_key, tf.Status.Handle); | |||||
| c_api.TF_DeleteFunction(_func_graph_handle); | |||||
| base.DisposeUnmanagedResources(handle); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -302,7 +302,7 @@ namespace Tensorflow | |||||
| public void device(string device_name) | public void device(string device_name) | ||||
| { | { | ||||
| throw new NotImplementedException(""); | |||||
| } | } | ||||
| private void _create_op_helper(Operation op, bool compute_device = true) | private void _create_op_helper(Operation op, bool compute_device = true) | ||||
| @@ -8,7 +8,7 @@ namespace Tensorflow.Keras.Engine | |||||
| { | { | ||||
| Tensors input_tensors { get; } | Tensors input_tensors { get; } | ||||
| Tensors Outputs { get; } | Tensors Outputs { get; } | ||||
| ILayer Layer { get; set; } | |||||
| ILayer Layer { get; } | |||||
| List<Tensor> KerasInputs { get; set; } | List<Tensor> KerasInputs { get; set; } | ||||
| INode[] ParentNodes { get; } | INode[] ParentNodes { get; } | ||||
| IEnumerable<(ILayer, int, int, Tensor)> iterate_inbound(); | IEnumerable<(ILayer, int, int, Tensor)> iterate_inbound(); | ||||
| @@ -11,14 +11,12 @@ | |||||
| public int NodeIndex => node_index; | public int NodeIndex => node_index; | ||||
| int tensor_index; | int tensor_index; | ||||
| public int TensorIndex => tensor_index; | public int TensorIndex => tensor_index; | ||||
| Tensor tensor; | |||||
| public KerasHistory(ILayer layer, int node_index, int tensor_index, Tensor tensor) | |||||
| public KerasHistory(ILayer layer, int node_index, int tensor_index) | |||||
| { | { | ||||
| this.layer = layer; | this.layer = layer; | ||||
| this.node_index = node_index; | this.node_index = node_index; | ||||
| this.tensor_index = tensor_index; | this.tensor_index = tensor_index; | ||||
| this.tensor = tensor; | |||||
| } | } | ||||
| public void Deconstruct(out ILayer layer, out int node_index, out int tensor_index) | public void Deconstruct(out ILayer layer, out int node_index, out int tensor_index) | ||||
| @@ -29,6 +27,6 @@ | |||||
| } | } | ||||
| public override string ToString() | public override string ToString() | ||||
| => $"{layer.GetType().Name} {layer.Name} {tensor.name}"; | |||||
| => $"{layer.GetType().Name} {layer.Name}"; | |||||
| } | } | ||||
| } | } | ||||
| @@ -16,6 +16,8 @@ namespace Tensorflow.Keras | |||||
| List<IVariableV1> trainable_weights { get; } | List<IVariableV1> trainable_weights { get; } | ||||
| List<IVariableV1> non_trainable_weights { get; } | List<IVariableV1> non_trainable_weights { get; } | ||||
| TensorShape output_shape { get; } | TensorShape output_shape { get; } | ||||
| TensorShape BatchInputShape { get; } | |||||
| TF_DataType DType { get; } | |||||
| int count_params(); | int count_params(); | ||||
| LayerArgs get_config(); | LayerArgs get_config(); | ||||
| } | } | ||||
| @@ -72,6 +72,10 @@ namespace Tensorflow | |||||
| public TensorShape output_shape => throw new NotImplementedException(); | public TensorShape output_shape => throw new NotImplementedException(); | ||||
| public TensorShape BatchInputShape => throw new NotImplementedException(); | |||||
| public TF_DataType DType => throw new NotImplementedException(); | |||||
| public RnnCell(bool trainable = true, | public RnnCell(bool trainable = true, | ||||
| string name = null, | string name = null, | ||||
| TF_DataType dtype = TF_DataType.DtInvalid, | TF_DataType dtype = TF_DataType.DtInvalid, | ||||
| @@ -65,7 +65,7 @@ namespace Tensorflow | |||||
| return gen_control_flow_ops.next_iteration(data, name: name); | return gen_control_flow_ops.next_iteration(data, name: name); | ||||
| } | } | ||||
| public static Operation Assert(Tensor condition, object[] data, long? summarize = null, string name = null) | |||||
| public static Operation Assert(Tensor condition, object[] data, long summarize = 3, string name = null) | |||||
| { | { | ||||
| if (tf.executing_eagerly()) | if (tf.executing_eagerly()) | ||||
| { | { | ||||
| @@ -82,7 +82,7 @@ namespace Tensorflow | |||||
| condition = ops.convert_to_tensor(condition, name: "Condition"); | condition = ops.convert_to_tensor(condition, name: "Condition"); | ||||
| Func<Operation[]> true_assert = () => | Func<Operation[]> true_assert = () => | ||||
| { | { | ||||
| var assert = gen_logging_ops._assert(condition, data, summarize, name: "Assert"); | |||||
| var assert = gen_logging_ops.assert(condition, data, summarize, name: "Assert"); | |||||
| return new Operation[] { assert }; | return new Operation[] { assert }; | ||||
| }; | }; | ||||
| @@ -21,10 +21,17 @@ namespace Tensorflow | |||||
| { | { | ||||
| public class gen_logging_ops | public class gen_logging_ops | ||||
| { | { | ||||
| public static Operation _assert(Tensor condition, object[] data, long? summarize = 3, string name = null) | |||||
| public static Operation assert(Tensor condition, object[] data, long summarize = 3, string name = null) | |||||
| { | { | ||||
| if (!summarize.HasValue) | |||||
| summarize = 3; | |||||
| if (tf.Context.executing_eagerly()) | |||||
| { | |||||
| var results = tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, | |||||
| "Assert", name, | |||||
| null, | |||||
| new object[] { condition, data, summarize }); | |||||
| return results[0]; | |||||
| } | |||||
| var _op = tf.OpDefLib._apply_op_helper("Assert", name, args: new { condition, data, summarize }); | var _op = tf.OpDefLib._apply_op_helper("Assert", name, args: new { condition, data, summarize }); | ||||
| @@ -68,7 +68,7 @@ namespace Tensorflow | |||||
| null, | null, | ||||
| resource, value); | resource, value); | ||||
| return results.Length == 0 ? null : results[0]; | |||||
| return null; | |||||
| } | } | ||||
| var _op = tf.OpDefLib._apply_op_helper("AssignVariableOp", name, new { resource, value }); | var _op = tf.OpDefLib._apply_op_helper("AssignVariableOp", name, new { resource, value }); | ||||
| @@ -113,7 +113,8 @@ namespace Tensorflow | |||||
| "container", container, | "container", container, | ||||
| "shared_name", shared_name, | "shared_name", shared_name, | ||||
| "dtype", dtype, | "dtype", dtype, | ||||
| "shape", shape.dims); | |||||
| "shape", shape.dims, | |||||
| "allowed_devices", new string[0]); | |||||
| return results[0]; | return results[0]; | ||||
| } | } | ||||
| @@ -129,6 +130,28 @@ namespace Tensorflow | |||||
| return _op.output; | return _op.output; | ||||
| } | } | ||||
| public static Tensor destroy_resource_op(Tensor resource, bool ignore_lookup_error = true, string name = null) | |||||
| { | |||||
| if (tf.Context.executing_eagerly()) | |||||
| { | |||||
| var results = tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, | |||||
| "DestroyResourceOp", name, | |||||
| null, | |||||
| resource, | |||||
| "ignore_lookup_error", ignore_lookup_error); | |||||
| return results.Length == 0 ? null : results[0]; | |||||
| } | |||||
| var _op = tf.OpDefLib._apply_op_helper("DestroyResourceOp", name, new | |||||
| { | |||||
| resource, | |||||
| ignore_lookup_error | |||||
| }); | |||||
| return _op.output; | |||||
| } | |||||
| /// <summary> | /// <summary> | ||||
| /// Reads the value of a variable. | /// Reads the value of a variable. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -26,7 +26,7 @@ namespace Tensorflow | |||||
| /// </summary> | /// </summary> | ||||
| public static class resource_variable_ops | public static class resource_variable_ops | ||||
| { | { | ||||
| public static ITensorOrOperation shape_safe_assign_variable_handle(Tensor handle, int[] shape, Tensor value, string name = null) | |||||
| public static Operation shape_safe_assign_variable_handle(Tensor handle, int[] shape, Tensor value, string name = null) | |||||
| { | { | ||||
| var value_tensor = ops.convert_to_tensor(value); | var value_tensor = ops.convert_to_tensor(value); | ||||
| return gen_resource_variable_ops.assign_variable_op(handle, | return gen_resource_variable_ops.assign_variable_op(handle, | ||||
| @@ -96,8 +96,10 @@ namespace Tensorflow | |||||
| // We create an assert Op instead of checking right away in order to be | // We create an assert Op instead of checking right away in order to be | ||||
| // compatible with ASYNC execution mode. Further, since not all devices | // compatible with ASYNC execution mode. Further, since not all devices | ||||
| // support string tensors, we encode the assertion string in the Op name | // support string tensors, we encode the assertion string in the Op name | ||||
| /*gen_logging_ops._assert( | |||||
| math_ops.logical_not(exists), [exists], name = "EagerVariableNameReuse");*/ | |||||
| /*gen_logging_ops.assert(gen_math_ops.logical_not(exists), | |||||
| new[] { exists }, | |||||
| name: "EagerVariableNameReuse");*/ | |||||
| var handle_data = new HandleData(); | var handle_data = new HandleData(); | ||||
| handle_data.IsSet = true; | handle_data.IsSet = true; | ||||
| handle_data.ShapeAndType.Add(new HandleShapeAndType | handle_data.ShapeAndType.Add(new HandleShapeAndType | ||||
| @@ -456,11 +456,6 @@ namespace Tensorflow | |||||
| private void _extend_graph() | private void _extend_graph() | ||||
| { } | { } | ||||
| public void close() | |||||
| { | |||||
| Dispose(); | |||||
| } | |||||
| protected override void DisposeUnmanagedResources(IntPtr handle) | protected override void DisposeUnmanagedResources(IntPtr handle) | ||||
| { | { | ||||
| lock (Locks.ProcessWide) | lock (Locks.ProcessWide) | ||||
| @@ -475,11 +475,11 @@ namespace Tensorflow | |||||
| size += TF_StringEncodedSize((ulong)b.Length); | size += TF_StringEncodedSize((ulong)b.Length); | ||||
| ulong src_size = size + (ulong)buffer.Length * sizeof(ulong); | ulong src_size = size + (ulong)buffer.Length * sizeof(ulong); | ||||
| IntPtr handle = TF_AllocateTensor(TF_DataType.TF_STRING, shape, shape.Length, src_size); | |||||
| _handle = TF_AllocateTensor(TF_DataType.TF_STRING, shape, shape.Length, src_size); | |||||
| AllocationType = AllocationType.Tensorflow; | AllocationType = AllocationType.Tensorflow; | ||||
| // Clear offset table | // Clear offset table | ||||
| IntPtr input = TF_TensorData(handle); | |||||
| IntPtr input = TensorDataPointer; | |||||
| IntPtr data_start = input + buffer.Length * sizeof(ulong); | IntPtr data_start = input + buffer.Length * sizeof(ulong); | ||||
| IntPtr limit = input + (int)src_size; | IntPtr limit = input + (int)src_size; | ||||
| ulong offset = 0; | ulong offset = 0; | ||||
| @@ -496,7 +496,9 @@ namespace Tensorflow | |||||
| } | } | ||||
| } | } | ||||
| _handle = handle; | |||||
| #if TRACK_TENSOR_LIFE | |||||
| print($"New Tensor 0x{_handle.ToString("x16")} {AllocationType} String Data: 0x{TensorDataPointer.ToString("x16")}"); | |||||
| #endif | |||||
| } | } | ||||
| public unsafe Tensor(NDArray nd, TF_DataType? tensorDType = null) | public unsafe Tensor(NDArray nd, TF_DataType? tensorDType = null) | ||||
| @@ -563,12 +565,13 @@ namespace Tensorflow | |||||
| { | { | ||||
| AllocationType = AllocationType.FromPointer; | AllocationType = AllocationType.FromPointer; | ||||
| AllocationHandle = arraySlice; | AllocationHandle = arraySlice; | ||||
| #if TRACK_TENSOR_LIFE | |||||
| print($"New Tensor {Id} {AllocationType} 0x{TensorDataPointer.ToString("x16")}"); | |||||
| #endif | |||||
| } | } | ||||
| else | else | ||||
| AllocationType = AllocationType.Tensorflow; | AllocationType = AllocationType.Tensorflow; | ||||
| #if TRACK_TENSOR_LIFE | |||||
| print($"New Tensor 0x{_handle.ToString("x16")} {AllocationType} Data: 0x{TensorDataPointer.ToString("x16")}"); | |||||
| #endif | |||||
| } | } | ||||
| public Tensor(Operation op, int value_index, TF_DataType dtype) | public Tensor(Operation op, int value_index, TF_DataType dtype) | ||||
| @@ -181,7 +181,6 @@ namespace Tensorflow | |||||
| storage.Allocate(new Shape(shape)); | storage.Allocate(new Shape(shape)); | ||||
| var bytesize = (long)this.bytesize; | |||||
| System.Buffer.MemoryCopy(buffer.ToPointer(), storage.Address, bytesize, bytesize); | System.Buffer.MemoryCopy(buffer.ToPointer(), storage.Address, bytesize, bytesize); | ||||
| return new NDArray(storage); | return new NDArray(storage); | ||||
| @@ -24,6 +24,7 @@ using System.Runtime.InteropServices; | |||||
| using Tensorflow.Eager; | using Tensorflow.Eager; | ||||
| using Tensorflow.Framework; | using Tensorflow.Framework; | ||||
| using Tensorflow.Keras.Engine; | using Tensorflow.Keras.Engine; | ||||
| using Tensorflow.Variables; | |||||
| using static Tensorflow.Binding; | using static Tensorflow.Binding; | ||||
| namespace Tensorflow | namespace Tensorflow | ||||
| @@ -260,12 +261,11 @@ namespace Tensorflow | |||||
| [SuppressMessage("ReSharper", "ConvertIfStatementToSwitchStatement")] | [SuppressMessage("ReSharper", "ConvertIfStatementToSwitchStatement")] | ||||
| protected override void DisposeUnmanagedResources(IntPtr handle) | protected override void DisposeUnmanagedResources(IntPtr handle) | ||||
| { | { | ||||
| if (AllocationHandle != null) | |||||
| { | |||||
| #if TRACK_TENSOR_LIFE | #if TRACK_TENSOR_LIFE | ||||
| print($"Delete AllocationHandle.{AllocationType} 0x{TensorDataPointer.ToString("x16")}"); | |||||
| print($"Delete Tensor 0x{handle.ToString("x16")} {AllocationType} Data: 0x{TensorDataPointer.ToString("x16")}"); | |||||
| #endif | #endif | ||||
| if (AllocationHandle != null) | |||||
| { | |||||
| if (AllocationType == AllocationType.GCHandle) | if (AllocationType == AllocationType.GCHandle) | ||||
| { | { | ||||
| ((GCHandle)AllocationHandle).Free(); | ((GCHandle)AllocationHandle).Free(); | ||||
| @@ -287,17 +287,9 @@ namespace Tensorflow | |||||
| throw new InvalidOperationException($"Tensor.AllocationHandle is not null ({AllocationHandle}) but AllocationType is not matched to a C# allocation type ({AllocationType})."); | throw new InvalidOperationException($"Tensor.AllocationHandle is not null ({AllocationHandle}) but AllocationType is not matched to a C# allocation type ({AllocationType})."); | ||||
| } | } | ||||
| #if TRACK_TENSOR_LIFE | |||||
| print($"Delete TensorHandle 0x{handle.ToString("x16")}"); | |||||
| #endif | |||||
| c_api.TF_DeleteTensor(handle); | c_api.TF_DeleteTensor(handle); | ||||
| } | } | ||||
| public virtual IntPtr ToPointer() | |||||
| => _handle; | |||||
| public bool IsDisposed => _disposed; | public bool IsDisposed => _disposed; | ||||
| // public int tensor_int_val { get; set; } | |||||
| } | } | ||||
| } | } | ||||
| @@ -43,6 +43,11 @@ namespace Tensorflow | |||||
| items.AddRange(tensors); | items.AddRange(tensors); | ||||
| } | } | ||||
| public Tensors(IEnumerable<Tensor> tensors) | |||||
| { | |||||
| items.AddRange(tensors); | |||||
| } | |||||
| public Tensors(NDArray nd) | public Tensors(NDArray nd) | ||||
| { | { | ||||
| items.Add(ops.convert_to_tensor(nd)); | items.Add(ops.convert_to_tensor(nd)); | ||||
| @@ -35,7 +35,7 @@ namespace Tensorflow | |||||
| this.name = name; | this.name = name; | ||||
| } | } | ||||
| public override ITensorOrOperation restore(Tensor[] restored_tensors, TensorShape[] restored_shapes = null) | |||||
| public override Operation restore(Tensor[] restored_tensors, TensorShape[] restored_shapes = null) | |||||
| { | { | ||||
| var restored_tensor = restored_tensors[0]; | var restored_tensor = restored_tensors[0]; | ||||
| restored_tensor = array_ops.identity(restored_tensor); | restored_tensor = array_ops.identity(restored_tensor); | ||||
| @@ -40,7 +40,7 @@ namespace Tensorflow | |||||
| this.name = name; | this.name = name; | ||||
| } | } | ||||
| public virtual ITensorOrOperation restore(Tensor[] restored_tensors, TensorShape[] restored_shapes = null) | |||||
| public virtual Operation restore(Tensor[] restored_tensors, TensorShape[] restored_shapes = null) | |||||
| { | { | ||||
| var restored_tensor = restored_tensors[0]; | var restored_tensor = restored_tensors[0]; | ||||
| return gen_state_ops.assign(op, | return gen_state_ops.assign(op, | ||||
| @@ -1,5 +1,7 @@ | |||||
| using NumSharp; | using NumSharp; | ||||
| using System; | using System; | ||||
| using Tensorflow.Eager; | |||||
| using Tensorflow.Variables; | |||||
| using static Tensorflow.Binding; | using static Tensorflow.Binding; | ||||
| namespace Tensorflow | namespace Tensorflow | ||||
| @@ -22,7 +24,6 @@ namespace Tensorflow | |||||
| public bool trainable => _trainable; | public bool trainable => _trainable; | ||||
| protected Tensor _initial_value; | protected Tensor _initial_value; | ||||
| public Tensor initial_value => _initial_value; | |||||
| public Operation initializer => initializer_op; | public Operation initializer => initializer_op; | ||||
| @@ -44,16 +45,12 @@ namespace Tensorflow | |||||
| public Operation Op => handle.op; | public Operation Op => handle.op; | ||||
| public Graph Graph => handle.graph; | public Graph Graph => handle.graph; | ||||
| public string Device => handle.Device; | public string Device => handle.Device; | ||||
| EagerResourceDeleter eager_resource_deleter; | |||||
| public BaseResourceVariable() | public BaseResourceVariable() | ||||
| { | { | ||||
| } | } | ||||
| public BaseResourceVariable(IntPtr handle, IntPtr tensor) | |||||
| { | |||||
| _handle = handle; | |||||
| } | |||||
| public void __init__(bool trainable = true, | public void __init__(bool trainable = true, | ||||
| Tensor handle = null, | Tensor handle = null, | ||||
| string name = null, | string name = null, | ||||
| @@ -66,7 +63,24 @@ namespace Tensorflow | |||||
| this.handle = handle; | this.handle = handle; | ||||
| _name = name; | _name = name; | ||||
| // handle_deleter | |||||
| // After the handle has been created, set up a way to clean it up when | |||||
| // executing eagerly. We'll hold the only reference to the deleter, so that | |||||
| // when this object is garbage collected the deleter will be too. This | |||||
| // means ResourceVariables can be part of reference cycles without those | |||||
| // cycles being uncollectable. | |||||
| if (handle.IsEagerTensor) | |||||
| { | |||||
| _handle = handle.EagerTensorHandle.DangerousGetHandle(); | |||||
| eager_resource_deleter = new EagerResourceDeleter(handle, handle.Device); | |||||
| } | |||||
| else | |||||
| { | |||||
| _handle = handle; | |||||
| } | |||||
| #if TRACK_TENSOR_LIFE | |||||
| print($"Created Resource 0x{_handle.ToString("x16")} {_name}"); | |||||
| #endif | |||||
| } | } | ||||
| public Tensor assign<T>(T value, bool use_locking = false, string name = null, bool read_value = true) | public Tensor assign<T>(T value, bool use_locking = false, string name = null, bool read_value = true) | ||||
| @@ -85,7 +99,7 @@ namespace Tensorflow | |||||
| if (read_value) | if (read_value) | ||||
| return gen_resource_variable_ops.read_variable_op(handle, dtype); | return gen_resource_variable_ops.read_variable_op(handle, dtype); | ||||
| return assign_op; | return assign_op; | ||||
| } | } | ||||
| @@ -214,6 +228,9 @@ namespace Tensorflow | |||||
| protected override void DisposeUnmanagedResources(IntPtr handle) | protected override void DisposeUnmanagedResources(IntPtr handle) | ||||
| { | { | ||||
| #if TRACK_TENSOR_LIFE | |||||
| print($"Deleted Resource 0x{handle.ToString("x16")} {_name}"); | |||||
| #endif | |||||
| } | } | ||||
| public Tensor AsTensor(TF_DataType dtype = TF_DataType.DtInvalid, string name = null, bool as_ref = false) | public Tensor AsTensor(TF_DataType dtype = TF_DataType.DtInvalid, string name = null, bool as_ref = false) | ||||
| @@ -0,0 +1,34 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| using static Tensorflow.Binding; | |||||
| namespace Tensorflow.Variables | |||||
| { | |||||
| public class EagerResourceDeleter : DisposableObject | |||||
| { | |||||
| Tensor _tensor; | |||||
| string _handle_device; | |||||
| public EagerResourceDeleter(Tensor handle, string handle_device) | |||||
| { | |||||
| _tensor = handle; | |||||
| _handle = handle.EagerTensorHandle.DangerousGetHandle(); | |||||
| _handle_device = handle_device; | |||||
| bool success = false; | |||||
| handle.EagerTensorHandle.DangerousAddRef(ref success); | |||||
| } | |||||
| protected override void DisposeUnmanagedResources(IntPtr handle) | |||||
| { | |||||
| // gen_resource_variable_ops.destroy_resource_op(_tensor, ignore_lookup_error: true); | |||||
| tf.device(_handle_device); | |||||
| tf.Runner.TFE_Execute(tf.Context, _handle_device, "DestroyResourceOp", | |||||
| new[] { _tensor }, | |||||
| new object[] { "ignore_lookup_error", true }, 0); | |||||
| _tensor.EagerTensorHandle.DangerousRelease(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -344,7 +344,7 @@ namespace Tensorflow | |||||
| return assign; | return assign; | ||||
| return assign.op; | return assign.op; | ||||
| } | } | ||||
| public override string ToString() | public override string ToString() | ||||
| { | { | ||||
| return $"tf.RefVariable '{Name}' shape={shape} dtype={dtype}"; | return $"tf.RefVariable '{Name}' shape={shape} dtype={dtype}"; | ||||
| @@ -78,8 +78,7 @@ namespace Tensorflow | |||||
| tf_with(ops.init_scope(), init_scope => | tf_with(ops.init_scope(), init_scope => | ||||
| { | { | ||||
| _in_graph_mode = !tf.Context.executing_eagerly(); | _in_graph_mode = !tf.Context.executing_eagerly(); | ||||
| var values = init_from_fn ? new object[0] : new object[] { initial_value }; | |||||
| tf_with(ops.name_scope(name, "Variable", values, skip_on_eager: false), scope => | |||||
| tf_with(ops.name_scope(name, "Variable", initial_value, skip_on_eager: false), scope => | |||||
| { | { | ||||
| name = scope; | name = scope; | ||||
| var handle_name = ops.name_from_scope_name(name); | var handle_name = ops.name_from_scope_name(name); | ||||
| @@ -103,19 +102,17 @@ namespace Tensorflow | |||||
| tf_with(ops.name_scope("Initializer"), delegate | tf_with(ops.name_scope("Initializer"), delegate | ||||
| { | { | ||||
| if (initial_value.GetType().GetInterface("IInitializer") != null) | if (initial_value.GetType().GetInterface("IInitializer") != null) | ||||
| initial_value = ops.convert_to_tensor((initial_value as IInitializer).Apply(new InitializerArgs(shape, dtype: dtype))); | |||||
| _initial_value = ops.convert_to_tensor((initial_value as IInitializer).Apply(new InitializerArgs(shape, dtype: dtype))); | |||||
| else | else | ||||
| { | { | ||||
| var value = init_from_fn ? (initial_value as Func<Tensor>)() : initial_value; | var value = init_from_fn ? (initial_value as Func<Tensor>)() : initial_value; | ||||
| initial_value = ops.convert_to_tensor(value, | |||||
| _initial_value = ops.convert_to_tensor(value, | |||||
| name: "initial_value", | name: "initial_value", | ||||
| dtype: dtype); | dtype: dtype); | ||||
| } | } | ||||
| }); | }); | ||||
| _shape = shape ?? (initial_value as Tensor).TensorShape; | |||||
| _initial_value = initial_value as Tensor; | |||||
| _shape = shape ?? _initial_value.TensorShape; | |||||
| if (_in_graph_mode) | if (_in_graph_mode) | ||||
| { | { | ||||
| @@ -141,7 +138,7 @@ namespace Tensorflow | |||||
| initializer_op = null; | initializer_op = null; | ||||
| _graph_element = null; | _graph_element = null; | ||||
| _dtype = _initial_value.dtype.as_base_dtype(); | _dtype = _initial_value.dtype.as_base_dtype(); | ||||
| initial_value = _in_graph_mode ? initial_value : null; | |||||
| // initial_value = _in_graph_mode ? initial_value : null; | |||||
| } | } | ||||
| base.__init__(trainable: trainable, | base.__init__(trainable: trainable, | ||||
| @@ -60,6 +60,18 @@ namespace Tensorflow | |||||
| bool use_locking = true, | bool use_locking = true, | ||||
| string name = null) | string name = null) | ||||
| { | { | ||||
| if (tf.executing_eagerly()) | |||||
| { | |||||
| var results = tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, | |||||
| "Assign", name, | |||||
| null, | |||||
| @ref, value, | |||||
| "validate_shape", validate_shape, | |||||
| "use_locking", use_locking); | |||||
| return results[0]; | |||||
| } | |||||
| var _op = tf.OpDefLib._apply_op_helper("Assign", name: name, args: new { @ref, value, validate_shape, use_locking }); | var _op = tf.OpDefLib._apply_op_helper("Assign", name: name, args: new { @ref, value, validate_shape, use_locking }); | ||||
| var _result = _op.outputs; | var _result = _op.outputs; | ||||
| @@ -101,7 +101,7 @@ namespace Tensorflow | |||||
| foreach (var op_input in op_input_list) | foreach (var op_input in op_input_list) | ||||
| { | { | ||||
| // Determine if this is a valid graph_element. | // Determine if this is a valid graph_element. | ||||
| var graph_element = op_input; | |||||
| // var graph_element = op_input; | |||||
| } | } | ||||
| return get_default_graph(); | return get_default_graph(); | ||||
| @@ -79,7 +79,7 @@ namespace Tensorflow | |||||
| return (null, null); | return (null, null); | ||||
| if (name == null) | if (name == null) | ||||
| name = ""; | |||||
| name = _default_name; | |||||
| var scope_name = name; | var scope_name = name; | ||||
| var old_name = ctx.ScopeName; | var old_name = ctx.ScopeName; | ||||
| @@ -118,10 +118,20 @@ namespace Tensorflow.Keras | |||||
| { | { | ||||
| tf.Context.reset_context(); | tf.Context.reset_context(); | ||||
| reset_uids(); | reset_uids(); | ||||
| ops.set_default_session(tf.Session(ops.get_default_graph())); | |||||
| // var phase = tf.placeholder_with_default(false, new int[] { }, name: "keras_learning_phase"); | // var phase = tf.placeholder_with_default(false, new int[] { }, name: "keras_learning_phase"); | ||||
| _GRAPH_LEARNING_PHASES = new Dictionary<Graph, GraphLearningPhase>(); | |||||
| _GRAPH_LEARNING_PHASES[tf.get_default_graph()] = 0; | |||||
| if (_GRAPH_LEARNING_PHASES != null) | |||||
| _GRAPH_LEARNING_PHASES.Clear(); | |||||
| if (_GRAPH_LEARNING_PHASES != null) | |||||
| _GRAPH_LEARNING_PHASES.Clear(); | |||||
| PER_GRAPH_LAYER_NAME_UIDS.Clear(); | |||||
| _CURRENT_SCRATCH_GRAPH = null; | |||||
| _GRAPH = null; | |||||
| ops.set_default_session(tf.Session(ops.get_default_graph())); | |||||
| tf.enable_eager_execution(); | |||||
| GC.Collect(); | |||||
| GC.WaitForPendingFinalizers(); | |||||
| } | } | ||||
| public void manual_variable_initialization(bool value) | public void manual_variable_initialization(bool value) | ||||
| { | { | ||||
| @@ -147,7 +157,7 @@ namespace Tensorflow.Keras | |||||
| if (ops.executing_eagerly_outside_functions()) | if (ops.executing_eagerly_outside_functions()) | ||||
| { | { | ||||
| foreach (var (x, value) in tuples) | foreach (var (x, value) in tuples) | ||||
| x.assign(value); | |||||
| x.assign(value, read_value: false); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -93,13 +93,11 @@ namespace Tensorflow.Keras.Engine.DataAdapters | |||||
| public IEnumerable<(int, OwnedIterator)> enumerate_epochs() | public IEnumerable<(int, OwnedIterator)> enumerate_epochs() | ||||
| { | { | ||||
| var data_iterator = new OwnedIterator(_dataset); | |||||
| foreach (var epoch in range(_initial_epoch, _epochs)) | foreach (var epoch in range(_initial_epoch, _epochs)) | ||||
| { | { | ||||
| if (_insufficient_data) | if (_insufficient_data) | ||||
| break; | break; | ||||
| if (_adapter.ShouldRecreateIterator()) | |||||
| data_iterator = new OwnedIterator(_dataset); | |||||
| using var data_iterator = new OwnedIterator(_dataset); | |||||
| yield return (epoch, data_iterator); | yield return (epoch, data_iterator); | ||||
| } | } | ||||
| } | } | ||||
| @@ -72,8 +72,8 @@ namespace Tensorflow.Keras.Engine.DataAdapters | |||||
| IDatasetV2 slice_inputs(IDatasetV2 indices_dataset, Tensors elements) | IDatasetV2 slice_inputs(IDatasetV2 indices_dataset, Tensors elements) | ||||
| { | { | ||||
| var dataset2 = tf.data.Dataset.from_tensor(elements).repeat(); | |||||
| var dataset = tf.data.Dataset.zip(indices_dataset, dataset2); | |||||
| var dataset = tf.data.Dataset.from_tensor(elements).repeat(); | |||||
| dataset = tf.data.Dataset.zip(indices_dataset, dataset); | |||||
| dataset = dataset.map(inputs => | dataset = dataset.map(inputs => | ||||
| { | { | ||||
| @@ -84,9 +84,7 @@ namespace Tensorflow.Keras.Engine.DataAdapters | |||||
| return new Tensors(results); | return new Tensors(results); | ||||
| }); | }); | ||||
| dataset = dataset.with_options(new DatasetOptions { }); | |||||
| return dataset; | |||||
| return dataset.with_options(new DatasetOptions { }); | |||||
| } | } | ||||
| public override int GetSize() | public override int GetSize() | ||||
| @@ -64,7 +64,7 @@ namespace Tensorflow.Keras.Engine | |||||
| { | { | ||||
| var (layer, node_index, tensor_index) = x.KerasHistory; | var (layer, node_index, tensor_index) = x.KerasHistory; | ||||
| _output_layers.append(layer); | _output_layers.append(layer); | ||||
| _output_coordinates.append(new KerasHistory(layer, node_index, tensor_index, x)); | |||||
| _output_coordinates.append(new KerasHistory(layer, node_index, tensor_index)); | |||||
| } | } | ||||
| // Build self._input_layers: | // Build self._input_layers: | ||||
| @@ -72,7 +72,7 @@ namespace Tensorflow.Keras.Engine | |||||
| { | { | ||||
| var (layer, node_index, tensor_index) = x.KerasHistory; | var (layer, node_index, tensor_index) = x.KerasHistory; | ||||
| _input_layers.append(layer); | _input_layers.append(layer); | ||||
| _input_coordinates.append(new KerasHistory(layer, node_index, tensor_index, x)); | |||||
| _input_coordinates.append(new KerasHistory(layer, node_index, tensor_index)); | |||||
| } | } | ||||
| // Keep track of the network's nodes and layers. | // Keep track of the network's nodes and layers. | ||||
| @@ -40,7 +40,8 @@ namespace Tensorflow.Keras.Engine | |||||
| outputs = Call(inputs, state: state, is_training: is_training); | outputs = Call(inputs, state: state, is_training: is_training); | ||||
| outputs = _set_connectivity_metadata_(inputs, outputs); | |||||
| // memory leak | |||||
| // _set_connectivity_metadata_(inputs, outputs); | |||||
| _handle_activity_regularization(inputs, outputs); | _handle_activity_regularization(inputs, outputs); | ||||
| _set_mask_metadata(inputs, outputs, null); | _set_mask_metadata(inputs, outputs, null); | ||||
| }); | }); | ||||
| @@ -40,8 +40,8 @@ namespace Tensorflow.Keras.Engine | |||||
| throw new NotImplementedException(""); | throw new NotImplementedException(""); | ||||
| outputs = Call(inputs); | outputs = Call(inputs); | ||||
| outputs = _set_connectivity_metadata_(inputs, outputs); | |||||
| _set_connectivity_metadata_(inputs, outputs); | |||||
| _handle_activity_regularization(inputs, outputs); | _handle_activity_regularization(inputs, outputs); | ||||
| _set_mask_metadata(inputs, outputs, null); | _set_mask_metadata(inputs, outputs, null); | ||||
| }); | }); | ||||
| @@ -120,15 +120,14 @@ namespace Tensorflow.Keras.Engine | |||||
| public void SetConnectivityMetadata(Tensors inputs, Tensors outputs) | public void SetConnectivityMetadata(Tensors inputs, Tensors outputs) | ||||
| => _set_connectivity_metadata_(inputs, outputs); | => _set_connectivity_metadata_(inputs, outputs); | ||||
| private Tensors _set_connectivity_metadata_(Tensors inputs, Tensors outputs) | |||||
| private void _set_connectivity_metadata_(Tensors inputs, Tensors outputs) | |||||
| { | { | ||||
| new Node(this, new NodeArgs | |||||
| var node = new Node(new NodeArgs | |||||
| { | { | ||||
| InputTensors = inputs, | InputTensors = inputs, | ||||
| Outputs = outputs | Outputs = outputs | ||||
| }); | }); | ||||
| return outputs; | |||||
| node.Connect(this); | |||||
| } | } | ||||
| private void _handle_activity_regularization(Tensors inputs, Tensors outputs) | private void _handle_activity_regularization(Tensors inputs, Tensors outputs) | ||||
| @@ -99,6 +99,9 @@ namespace Tensorflow.Keras.Engine | |||||
| var result_pairs = string.Join(", ", results.Select(x => $"{x.Item1}: {(float)x.Item2:F6}")); | var result_pairs = string.Join(", ", results.Select(x => $"{x.Item1}: {(float)x.Item2:F6}")); | ||||
| Console.WriteLine($"Epoch: {epoch + 1:D3}/{epochs:D3}, Step: {step + 1:D4}/{data_handler.Inferredsteps:D4}, {result_pairs}"); | Console.WriteLine($"Epoch: {epoch + 1:D3}/{epochs:D3}, Step: {step + 1:D4}/{data_handler.Inferredsteps:D4}, {result_pairs}"); | ||||
| } | } | ||||
| GC.Collect(); | |||||
| GC.WaitForPendingFinalizers(); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -59,6 +59,8 @@ namespace Tensorflow.Keras.Engine | |||||
| var end_step = step + data_handler.StepIncrement; | var end_step = step + data_handler.StepIncrement; | ||||
| // callbacks.on_predict_batch_end(end_step, {'outputs': batch_outputs}) | // callbacks.on_predict_batch_end(end_step, {'outputs': batch_outputs}) | ||||
| } | } | ||||
| GC.Collect(); | |||||
| GC.WaitForPendingFinalizers(); | |||||
| } | } | ||||
| // callbacks.on_predict_end() | // callbacks.on_predict_end() | ||||
| return outputs; | return outputs; | ||||
| @@ -40,7 +40,8 @@ namespace Tensorflow.Keras.Engine | |||||
| public TensorShape[] input_shapes; | public TensorShape[] input_shapes; | ||||
| public TensorShape[] output_shapes; | public TensorShape[] output_shapes; | ||||
| public List<Tensor> KerasInputs { get; set; } = new List<Tensor>(); | public List<Tensor> KerasInputs { get; set; } = new List<Tensor>(); | ||||
| public ILayer Layer { get; set; } | |||||
| ILayer _layer; | |||||
| public ILayer Layer => _layer; | |||||
| public bool is_input => args.InputTensors == null; | public bool is_input => args.InputTensors == null; | ||||
| public long[] FlatInputIds { get; set; } | public long[] FlatInputIds { get; set; } | ||||
| public long[] FlatOutputIds { get; set; } | public long[] FlatOutputIds { get; set; } | ||||
| @@ -61,19 +62,24 @@ namespace Tensorflow.Keras.Engine | |||||
| } | } | ||||
| } | } | ||||
| public Node(Layer layer, NodeArgs args) | |||||
| public Node(NodeArgs args) | |||||
| { | { | ||||
| this.args = args; | this.args = args; | ||||
| this.Layer = layer; | |||||
| } | |||||
| public void Connect(Layer layer) | |||||
| { | |||||
| _layer = layer; | |||||
| if (args.InputTensors != null) | if (args.InputTensors != null) | ||||
| KerasInputs.AddRange(args.InputTensors); | KerasInputs.AddRange(args.InputTensors); | ||||
| foreach (var (i, ele) in enumerate(KerasInputs)) | foreach (var (i, ele) in enumerate(KerasInputs)) | ||||
| _keras_inputs_ids_and_indices[i] = ele.Id; | _keras_inputs_ids_and_indices[i] = ele.Id; | ||||
| // Wire up Node to Layers. | // Wire up Node to Layers. | ||||
| layer.InboundNodes.Add(this); | layer.InboundNodes.Add(this); | ||||
| foreach (var kt in KerasInputs) | foreach (var kt in KerasInputs) | ||||
| { | { | ||||
| if (kt.KerasHistory == null) | if (kt.KerasHistory == null) | ||||
| @@ -86,7 +92,7 @@ namespace Tensorflow.Keras.Engine | |||||
| // Set metadata on outputs. | // Set metadata on outputs. | ||||
| var node_index = layer.InboundNodes.Count - 1; | var node_index = layer.InboundNodes.Count - 1; | ||||
| foreach (var (i, tensor) in enumerate(Outputs)) | foreach (var (i, tensor) in enumerate(Outputs)) | ||||
| tensor.KerasHistory = new KerasHistory(layer, node_index, i, tensor); | |||||
| tensor.KerasHistory = new KerasHistory(layer, node_index, i); | |||||
| // Cached for performance. | // Cached for performance. | ||||
| FlatInputIds = KerasInputs.Select(x => x.Id).ToArray(); | FlatInputIds = KerasInputs.Select(x => x.Id).ToArray(); | ||||
| @@ -64,7 +64,7 @@ namespace Tensorflow.Keras.Engine | |||||
| public void add(Tensor tensor) | public void add(Tensor tensor) | ||||
| { | { | ||||
| var layer = tensor.KerasHistory.Layer as Layer; | |||||
| var layer = tensor.KerasHistory.Layer; | |||||
| add(layer); | add(layer); | ||||
| } | } | ||||
| @@ -72,7 +72,7 @@ namespace Tensorflow.Keras.Engine | |||||
| /// Adds a layer instance on top of the layer stack. | /// Adds a layer instance on top of the layer stack. | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="layer"></param> | /// <param name="layer"></param> | ||||
| public void add(Layer layer) | |||||
| public void add(ILayer layer) | |||||
| { | { | ||||
| built = false; | built = false; | ||||
| var set_inputs = false; | var set_inputs = false; | ||||
| @@ -90,10 +90,11 @@ namespace Tensorflow.Keras.Layers | |||||
| // and set output_tensors' _keras_history. | // and set output_tensors' _keras_history. | ||||
| // input_tensor._keras_history = base_layer.KerasHistory(self, 0, 0) | // input_tensor._keras_history = base_layer.KerasHistory(self, 0, 0) | ||||
| // input_tensor._keras_mask = None | // input_tensor._keras_mask = None | ||||
| new Node(this, new NodeArgs | |||||
| var node = new Node(new NodeArgs | |||||
| { | { | ||||
| Outputs = args.InputTensor | Outputs = args.InputTensor | ||||
| }); | }); | ||||
| node.Connect(this); | |||||
| typeSpec = new TensorSpec(args.InputTensor.TensorShape, | typeSpec = new TensorSpec(args.InputTensor.TensorShape, | ||||
| dtype: args.InputTensor.dtype, | dtype: args.InputTensor.dtype, | ||||
| @@ -42,15 +42,13 @@ namespace Tensorflow.Keras.Utils | |||||
| Func<Tensor> init_val = () => args.Initializer.Apply(new InitializerArgs(args.Shape, dtype: args.DType)); | Func<Tensor> init_val = () => args.Initializer.Apply(new InitializerArgs(args.Shape, dtype: args.DType)); | ||||
| var variable_dtype = args.DType.as_base_dtype(); | var variable_dtype = args.DType.as_base_dtype(); | ||||
| var v = tf.Variable(init_val, | |||||
| return tf.Variable(init_val, | |||||
| dtype: variable_dtype, | dtype: variable_dtype, | ||||
| shape: args.Shape, | shape: args.Shape, | ||||
| name: args.Name, | name: args.Name, | ||||
| trainable: args.Trainable, | trainable: args.Trainable, | ||||
| validate_shape: args.ValidateShape, | validate_shape: args.ValidateShape, | ||||
| use_resource: args.UseResource); | use_resource: args.UseResource); | ||||
| return v; | |||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| @@ -51,6 +51,8 @@ namespace Tensorflow.Benchmark.Leak | |||||
| metrics: new[] { "accuracy" }); | metrics: new[] { "accuracy" }); | ||||
| model.fit(inputImages, outLables, batch_size: 32, epochs: 200); | model.fit(inputImages, outLables, batch_size: 32, epochs: 200); | ||||
| keras.backend.clear_session(); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -8,13 +8,13 @@ namespace Tensorflow.Native.UnitTest | |||||
| /// `class CApiAttributesTest` | /// `class CApiAttributesTest` | ||||
| /// </summary> | /// </summary> | ||||
| [TestClass] | [TestClass] | ||||
| public class CApiAttributesTestcs : CApiTest, IDisposable | |||||
| public class AttributesTestcs : CApiTest, IDisposable | |||||
| { | { | ||||
| private Graph graph_; | private Graph graph_; | ||||
| private int counter_; | private int counter_; | ||||
| private Status s_; | private Status s_; | ||||
| public CApiAttributesTestcs() | |||||
| public AttributesTestcs() | |||||
| { | { | ||||
| s_ = new Status(); | s_ = new Status(); | ||||
| graph_ = new Graph(); | graph_ = new Graph(); | ||||
| @@ -11,7 +11,7 @@ namespace Tensorflow.Native.UnitTest | |||||
| /// `class CApiColocationTest` | /// `class CApiColocationTest` | ||||
| /// </summary> | /// </summary> | ||||
| [TestClass] | [TestClass] | ||||
| public class CApiFunctionTest : CApiTest, IDisposable | |||||
| public class FunctionTest : CApiTest, IDisposable | |||||
| { | { | ||||
| Graph func_graph_; | Graph func_graph_; | ||||
| Graph host_graph_; | Graph host_graph_; | ||||
| @@ -10,7 +10,7 @@ namespace Tensorflow.Native.UnitTest | |||||
| /// `class CApiGradientsTest` | /// `class CApiGradientsTest` | ||||
| /// </summary> | /// </summary> | ||||
| [TestClass] | [TestClass] | ||||
| public class CApiGradientsTest : CApiTest, IDisposable | |||||
| public class GradientsTest : CApiTest, IDisposable | |||||
| { | { | ||||
| private Graph graph_ = new Graph(); | private Graph graph_ = new Graph(); | ||||
| private Graph expected_graph_ = new Graph(); | private Graph expected_graph_ = new Graph(); | ||||
| @@ -48,6 +48,16 @@ namespace TensorFlowNET.UnitTest.Basics | |||||
| Assert.AreEqual(11f, (float)v1.numpy()); | Assert.AreEqual(11f, (float)v1.numpy()); | ||||
| } | } | ||||
| [TestMethod] | |||||
| public void Assign3() | |||||
| { | |||||
| var v1 = tf.Variable(10.0f, name: "v1"); | |||||
| var v2 = tf.Variable(v1, name: "v2"); | |||||
| Assert.AreEqual(v1.numpy(), v2.numpy()); | |||||
| v1.assign(30.0f); | |||||
| Assert.AreNotEqual(v1.numpy(), v2.numpy()); | |||||
| } | |||||
| /// <summary> | /// <summary> | ||||
| /// Assign tensor to slice of other tensor. | /// Assign tensor to slice of other tensor. | ||||
| /// https://www.tensorflow.org/api_docs/python/tf/Variable#__getitem__ | /// https://www.tensorflow.org/api_docs/python/tf/Variable#__getitem__ | ||||