From 61541bacb94aa955e20d9bcd551b3f4b8b377fe2 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Thu, 4 Jan 2024 02:12:47 +0800 Subject: [PATCH 001/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index 2af0004102..c59c439997 100644 --- a/python/setup.py +++ b/python/setup.py @@ -112,7 +112,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.14.dev16", + version="0.8.14a16", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From b19b22eb29bad22e013f03729fef8aa141244db1 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Thu, 4 Jan 2024 02:13:04 +0800 Subject: [PATCH 002/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 0d8af43eb8..ceb951a786 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.14.dev16" +__version__ = "0.8.14a16" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From 63a10ba7848107af1d2517c94c9f7530d80c3963 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Mon, 8 Jan 2024 15:19:07 +0800 Subject: [PATCH 003/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index 8958eb8848..5aab3dc8c2 100644 --- a/python/setup.py +++ b/python/setup.py @@ -112,7 +112,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.14a21", + version="0.8.14b1", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 9a010bd143152b6da0b9dc28289b0f88887fa315 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Mon, 8 Jan 2024 15:19:30 +0800 Subject: [PATCH 004/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index fde7ba3ec3..a359f4f4e3 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.14a21" +__version__ = "0.8.14b1" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From d0bccd2c25841d45bcc41ed90e79380604f99504 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Mon, 8 Jan 2024 20:51:17 +0800 Subject: [PATCH 005/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index a671257cf7..764af44798 100644 --- a/python/setup.py +++ b/python/setup.py @@ -112,7 +112,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.14b2", + version="0.8.14a22", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 94ffa8d7294479ca1ffb036bce5158642996c25f Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Mon, 8 Jan 2024 20:51:41 +0800 Subject: [PATCH 006/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 4a566eb098..648e11cdc5 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.14b2" +__version__ = "0.8.14a22" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From 6fbf85c6a79a851248451f4376fc2c0803e1f8c6 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Tue, 9 Jan 2024 02:14:10 +0800 Subject: [PATCH 007/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index a671257cf7..61e32c451e 100644 --- a/python/setup.py +++ b/python/setup.py @@ -112,7 +112,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.14b2", + version="0.8.14", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From efdff3a5be70e21c7b472590f1793767c5dd3018 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Tue, 9 Jan 2024 02:14:38 +0800 Subject: [PATCH 008/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 4a566eb098..faf555a960 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.14b2" +__version__ = "0.8.14" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From 6cfa447536d5fcbdd22e21c0e7a292a904cd8509 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Fri, 12 Jan 2024 22:29:06 +0800 Subject: [PATCH 009/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index 2360e78b2d..9e44587b39 100644 --- a/python/setup.py +++ b/python/setup.py @@ -113,7 +113,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.15", + version="0.8.15a2", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 05a1275ab0d05ea9af15e95559098b7a3b7bade1 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Fri, 12 Jan 2024 22:29:29 +0800 Subject: [PATCH 010/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 0ed71dac42..91f5ca4371 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.15" +__version__ = "0.8.15a2" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From 4a698becc9aca16797a059f5031c79f3a01ec178 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Fri, 12 Jan 2024 23:00:26 +0800 Subject: [PATCH 011/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index 02217617ba..9dc11e5252 100644 --- a/python/setup.py +++ b/python/setup.py @@ -113,7 +113,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.17a1", + version="0.8.16", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 99599f996056056f44a881e74982fef1630ac434 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Fri, 12 Jan 2024 23:00:41 +0800 Subject: [PATCH 012/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index dac2290add..f478efef71 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.17a1" +__version__ = "0.8.16" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From 3d93c76018578f0399fa9716fa98a69061de951c Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 16 Jan 2024 01:10:55 +0800 Subject: [PATCH 013/135] [DevOps] update devops files. --- python/fedml/__init__.py | 2 +- .../ssl/open-release.fedml.ai_bundle.crt | 70 +++++++++---------- python/setup.py | 2 +- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index f478efef71..300607d5fa 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.16" +__version__ = "0.8.17" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release diff --git a/python/fedml/core/mlops/ssl/open-release.fedml.ai_bundle.crt b/python/fedml/core/mlops/ssl/open-release.fedml.ai_bundle.crt index 341059d2cc..63f3e443ba 100644 --- a/python/fedml/core/mlops/ssl/open-release.fedml.ai_bundle.crt +++ b/python/fedml/core/mlops/ssl/open-release.fedml.ai_bundle.crt @@ -1,39 +1,39 @@ -----BEGIN CERTIFICATE----- -MIIGZzCCBM+gAwIBAgIRAPBAl2SHMELT+NP8BGzTI6YwDQYJKoZIhvcNAQEMBQAw -WTELMAkGA1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs -IEluYy4xIzAhBgNVBAMTGlRydXN0QXNpYSBSU0EgRFYgVExTIENBIEcyMB4XDTIz -MDExNTAwMDAwMFoXDTI0MDExNTIzNTk1OVowGDEWMBQGA1UEAxMNb3Blbi5mZWRt -bC5haTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALcSEbXBBZ04WEoV -z3/jvbDhvPZHVSh8SWXhoamr3Piyag+GgR9xD4G0BfSdVJbOu21CaG4kmoJnM5sK -NsZ7txkxgVX0MldsNWC1Krtwjs0Q8uIZH9o6Efukcn8AhQUYcMge0hsXDfdH6OqF -rBrrOcC3PeGMeCS8XwCB3PIvNwlS3KDR3FBvCtJmjNjio2GNVNWfjhICE5cHg7Qp -2ON3z53ZyyBZEr2aV9l6JN0JbxsheSI0P/nag9Z47E/R4OIVf9SlU7NUM8S6SC58 -YIqdo++9dDkIGxCFE6DkaFY9lIi1z3ocM4z8//EwcjAoXj3cx7EfFlmvg6UWcOHl -5XfkCOcCAwEAAaOCAukwggLlMB8GA1UdIwQYMBaAFF86fBEQfgxncWHci6O1AANn -9VccMB0GA1UdDgQWBBTbetHnMn+gzrrd8kgzqebiwfuJKTAOBgNVHQ8BAf8EBAMC -BaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw -SQYDVR0gBEIwQDA0BgsrBgEEAbIxAQICMTAlMCMGCCsGAQUFBwIBFhdodHRwczov -L3NlY3RpZ28uY29tL0NQUzAIBgZngQwBAgEwfQYIKwYBBQUHAQEEcTBvMEIGCCsG -AQUFBzAChjZodHRwOi8vY3J0LnRydXN0LXByb3ZpZGVyLmNuL1RydXN0QXNpYVJT -QURWVExTQ0FHMi5jcnQwKQYIKwYBBQUHMAGGHWh0dHA6Ly9vY3NwLnRydXN0LXBy -b3ZpZGVyLmNuMBgGA1UdEQQRMA+CDW9wZW4uZmVkbWwuYWkwggGABgorBgEEAdZ5 -AgQCBIIBcASCAWwBagB3AHb/iD8KtvuVUcJhzPWHujS0pM27KdxoQgqf5mdMWjp0 -AAABhbX33agAAAQDAEgwRgIhANmqVPPSLA8x1B7AYDgQrfuZFqveh9ieMtguyIs1 -WDGOAiEA2WE2ZHsWDdXgk66vouZVDy1yiwlzWdxnjO5sO1sRJwIAdwDatr9rP7W2 -Ip+bwrtca+hwkXFsu1GEhTS9pD0wSNf7qwAAAYW1992iAAAEAwBIMEYCIQDSFCff -pK2Nj0sXIOGphQVM1iY+TozCseHdoT3LmixX9QIhAPhlJVCeON4ofgSViF8/0N9Q -XAfKKNf7T/OSmw3h1CgFAHYA7s3QZNXbGs7FXLedtM0TojKHRny87N7DUUhZRnEf -tZsAAAGFtffdfQAABAMARzBFAiAiLSQpYHvNVW5TLOLcmpQVr+9ADO3IXJFGKYTr -cQaXKQIhAOY5IZ2pNGH5crF2tN7FDZ2U/l8wz1JUIWrqmViVYmj/MA0GCSqGSIb3 -DQEBDAUAA4IBgQCDMEq04Bgz3h1F2r93383a4hjondgqjXEVbJUc8YHIhLS0I4rA -mqX9xUreadKV0hYTDzST70wjHv5O4oru0Er3xVNRY+L6zHsNspUrcJ8/p73nqJ3x -qpBmFFRPhB8y33CcGlWk+VTW/VD34ZleXJulvZLfG+6f41d9+xaJUGMZ27Cbl97U -tbqvkxwa4JpwnCK+I9rLw8wgCS+4gey1l12u8CPwCrnUDFLjjbely8XieJQPQo64 -tZhd8BBDJmW6YfWj7ztQwJ5O4oA7nZTPzL7VsyXpYsPcVkWDmmP2/aIBet8q7sKr -LYuJKvBND+9bHOn4FTrKK+6JZw2ox4ETjMlrW4t/5E22aBi664lCn3f1K1N8XABX -v7h2uujtZXFzlyG9IoKF/St0fz8em7M1L7j1yojErX/aHJUKedIKA02ogcK6KF+U -etGtouAXDvwVxsOTpHK4SVFbr0wwjm59Mo3Mj0XlWA1feCrYPsYu6XGpftxecwm9 -f0b7bYboRmZACRw= +MIIGZDCCBMygAwIBAgIQHwySP0TJJzfSHgtj+GvjNDANBgkqhkiG9w0BAQwFADBZ +MQswCQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywg +SW5jLjEjMCEGA1UEAxMaVHJ1c3RBc2lhIFJTQSBEViBUTFMgQ0EgRzIwHhcNMjQw +MTE1MDAwMDAwWhcNMjUwMTE4MjM1OTU5WjAYMRYwFAYDVQQDEw1vcGVuLmZlZG1s +LmFpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAryS1nV+ilqLkPC2y +l5reZTpjB+D7RKoRGRS8A4H6d2y5sHk0nLxcfcOEnjArPe4JWuXQ6Gf6knnCXd/n +uU24lIOCtF8Oo0mLprRb6IY7gH1QZ5zBuq9oAzq2KTK/ukfc0mMlLE4TwhmHych4 +W0LGoaXjq4eK1/Q48iQQyTKsHU03KLHOhls6aDLw15Vq/MifYRf1O3n01IU+RcUG +Bo2djU/zcs/Imirlv7fjo44SKGcTyfXgILx9bkz7yPyo1g7kpvbq4vYsJHA64Jc7 +XmHG1pvfRZADC8vxHgxYgT2W1h+igqH9JsTtKqy6Usk2Zl/FTIUpm5M6+y6s03e7 +GmCtVQIDAQABo4IC5zCCAuMwHwYDVR0jBBgwFoAUXzp8ERB+DGdxYdyLo7UAA2f1 +VxwwHQYDVR0OBBYEFE9jInLdJ82Ph0lmPrHmGCUfHndjMA4GA1UdDwEB/wQEAwIF +oDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBJ +BgNVHSAEQjBAMDQGCysGAQQBsjEBAgIxMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8v +c2VjdGlnby5jb20vQ1BTMAgGBmeBDAECATB9BggrBgEFBQcBAQRxMG8wQgYIKwYB +BQUHMAKGNmh0dHA6Ly9jcnQudHJ1c3QtcHJvdmlkZXIuY24vVHJ1c3RBc2lhUlNB +RFZUTFNDQUcyLmNydDApBggrBgEFBQcwAYYdaHR0cDovL29jc3AudHJ1c3QtcHJv +dmlkZXIuY24wGAYDVR0RBBEwD4INb3Blbi5mZWRtbC5haTCCAX4GCisGAQQB1nkC +BAIEggFuBIIBagFoAHYAzxFW7tUufK/zh1vZaS6b6RpxZ0qwF+ysAdJbd87MOwgA +AAGNDCCQygAABAMARzBFAiEA7BLwf733vAiw/mOi1TruraR3+dAhBx5dUzkXHuIi +lh0CICHaJFjN5nkr3M0g5jBV/bLdkV6JVDxAVrLMF39HkWymAHcAouMK5EXvva2b +fjjtR2d3U9eCW4SU1yteGyzEuVCkR+cAAAGNDCCQuQAABAMASDBGAiEAyGVPplPz +vytw4FmwXI2ehgjWUxIyXZJ69i2R49uMPd0CIQCwFqXCiRSZL0S66qz/7eD/5yAu +3744mfMI+yfre3qYugB1AE51oydcmhDDOFts1N8/Uusd8OCOG41pwLH6ZLFimjnf +AAABjQwgkKoAAAQDAEYwRAIgJxC6Afcl2jgGxNca+WP7oY2knJ2Rk+BaoZ28oOq2 +/2QCICR9FtTyCqlHHs5iE3Dq1zAb1F9UMkATxVhe9u/nLh49MA0GCSqGSIb3DQEB +DAUAA4IBgQCNA291er/nMVtWgfM5xqhWJNokS/Dkjp1z7LHqJ31ogxM01+BqBZVg +zTYFezzYpRVAoaLCW010u1/cuvEqOVX8SoNHECqK/dkTK4c3suB26xpaorskzufI +7ir9o68wY71Eg+Zc8JB6v8qrnv/sWWXNdYaFmkTsuEi6XpafU6KHTCVPR3OMAA3P +dgaGfZ1+FrY+Lq0/O2XEDd08oTObHQx+LahPIM64VORdwSm+6SE/2W1cZuadloAP +7ylZ3JMPuxUJQv/ULvQU5zf/C5G09sde5fjYBT+/mZ4oraFUFtiJqstQvEXbj4Xz +TlxxmLUTKiDTXQAbvf/UT4C9Ux3h6jhJdY4oAcHhghCo4GBCsKvvXwf3mky4L8SO +pqbJ+33oTDXEv8LwxmffLf/S2gkQWhujeuKfXooFNgLg3hkNKk6SBV+KsF2A7dx4 +C7RUTStq4gNRvRLxmhCVhTfcI2iiLLds4jPTkPHJiPX+lGWaEavcu6xW7CPgTB3J +0s56lBq7hEA= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFBzCCA++gAwIBAgIRALIM7VUuMaC/NDp1KHQ76aswDQYJKoZIhvcNAQELBQAw diff --git a/python/setup.py b/python/setup.py index 9dc11e5252..115966069a 100644 --- a/python/setup.py +++ b/python/setup.py @@ -113,7 +113,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.16", + version="0.8.17", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 22f0b03862535289db3123087eca4ef5d7fcda01 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Tue, 16 Jan 2024 12:38:49 +0800 Subject: [PATCH 014/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index 115966069a..a94a6d9b53 100644 --- a/python/setup.py +++ b/python/setup.py @@ -113,7 +113,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.17", + version="0.8.18a1", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 71ac70affb2a74853bf734af6a02cd1c12301856 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Tue, 16 Jan 2024 12:39:07 +0800 Subject: [PATCH 015/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 300607d5fa..d1888095c0 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.17" +__version__ = "0.8.18a1" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From b80de2ef6800aeeec384faa0207ac12ac0976285 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Thu, 18 Jan 2024 11:43:48 +0800 Subject: [PATCH 016/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index a94a6d9b53..4ec54f1e83 100644 --- a/python/setup.py +++ b/python/setup.py @@ -113,7 +113,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.18a1", + version="0.8.18a2", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 87eca429446cebf1d8f1536451072f22f4cafed5 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Thu, 18 Jan 2024 11:44:04 +0800 Subject: [PATCH 017/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index d1888095c0..afcc4ba9ea 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.18a1" +__version__ = "0.8.18a2" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From ee95bf4b5ba3c011a5c409c433a26d2c3681aafe Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Mon, 29 Jan 2024 15:27:45 +0800 Subject: [PATCH 018/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index 52315231ae..8990b94e7b 100644 --- a/python/setup.py +++ b/python/setup.py @@ -113,7 +113,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.18a6", + version="0.8.18b6", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 06b0890622d928115a34bb6ae14c59358456450c Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Mon, 29 Jan 2024 15:28:11 +0800 Subject: [PATCH 019/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 0e7549f428..7fae49aae2 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.18a6" +__version__ = "0.8.18b6" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From 0f71ac9f8e37272e0fb9211df1686ce40365726f Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Wed, 31 Jan 2024 13:56:00 +0800 Subject: [PATCH 020/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index f8bc1c8c3f..58b8c405c4 100644 --- a/python/setup.py +++ b/python/setup.py @@ -113,7 +113,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.18b7", + version="0.8.18a7", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 979d73c3e1800978fce6ecec1a2e5b8fc59428a7 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Wed, 31 Jan 2024 13:56:19 +0800 Subject: [PATCH 021/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 7e4f47c2e8..987f85eb5f 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.18b7" +__version__ = "0.8.18a7" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From 601b5344734a3b938b5c1cba44cc42c7b2b0c38a Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Thu, 1 Feb 2024 00:10:38 +0800 Subject: [PATCH 022/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index 07a7785b02..1cf6473f18 100644 --- a/python/setup.py +++ b/python/setup.py @@ -113,7 +113,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.18a8", + version="0.8.18b8", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From ae45145fe78306731a97230a6b2d44beef974800 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Thu, 1 Feb 2024 00:10:54 +0800 Subject: [PATCH 023/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index f0374d7b6c..8385173cce 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.18a8" +__version__ = "0.8.18b8" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From 6ad0c974ea3302749d6c7ded415844b3944ed5aa Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Thu, 1 Feb 2024 02:49:14 +0800 Subject: [PATCH 024/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index d78f63c83b..8895054455 100644 --- a/python/setup.py +++ b/python/setup.py @@ -113,7 +113,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.18b9", + version="0.8.18a9", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From be0ba71ccde4b47e2a67ef111462f7eb86d54f52 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Thu, 1 Feb 2024 02:49:33 +0800 Subject: [PATCH 025/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 6824992223..2c6535f3b7 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.18b9" +__version__ = "0.8.18a9" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From ef6a5f3d7ac262e2a3adc5814a5fd282c413aec9 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Thu, 1 Feb 2024 23:22:49 +0800 Subject: [PATCH 026/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index a650e56cbf..0f702cea13 100644 --- a/python/setup.py +++ b/python/setup.py @@ -113,7 +113,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.18a10", + version="0.8.18b10", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 0118e08256c5bf6f6659fea6f93d7fe19fca6cd1 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Thu, 1 Feb 2024 23:23:14 +0800 Subject: [PATCH 027/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 84b40c9552..3f29b8be35 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.18a10" +__version__ = "0.8.18b10" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From ba65649122fdafb80ec228b52b0e3fc8158cc108 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Fri, 2 Feb 2024 16:51:56 +0800 Subject: [PATCH 028/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index 1ac721d9fb..578c6e6067 100644 --- a/python/setup.py +++ b/python/setup.py @@ -114,7 +114,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.18b11", + version="0.8.18a11", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From fbc8dd8aacb4d659c7144421e95135d5a1a6b7ba Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Fri, 2 Feb 2024 16:52:14 +0800 Subject: [PATCH 029/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 4522f21d3a..2e95fedeeb 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.18b11" +__version__ = "0.8.18a11" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From 82e07233d87bdd1fa6e1456f1dde7d09affd55f8 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Sat, 3 Feb 2024 17:27:51 +0800 Subject: [PATCH 030/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index 05a0ba4c50..68c693c951 100644 --- a/python/setup.py +++ b/python/setup.py @@ -114,7 +114,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.18a13", + version="0.8.18b13", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 1dcd88906ad3875cb588d6f2f1072a8789216fe5 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Sat, 3 Feb 2024 17:28:07 +0800 Subject: [PATCH 031/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 81e864b2ea..181ff83f82 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.18a13" +__version__ = "0.8.18b13" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From a510bfc36a37853624aa067d2d4743492d8432e1 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Sat, 3 Feb 2024 23:45:57 +0800 Subject: [PATCH 032/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index fc10fac235..e918ac7264 100644 --- a/python/setup.py +++ b/python/setup.py @@ -114,7 +114,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.18b14", + version="0.8.18a14", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 0cc3242146434a85b9391352e750395247c02c04 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Sat, 3 Feb 2024 23:46:14 +0800 Subject: [PATCH 033/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index ccdf28d4cc..4e0635dc8a 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.18b14" +__version__ = "0.8.18a14" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From df6f03be4506314a246038551d25c3a9db91c436 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Sat, 3 Feb 2024 23:47:13 +0800 Subject: [PATCH 034/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index e918ac7264..b0efbaa94e 100644 --- a/python/setup.py +++ b/python/setup.py @@ -114,7 +114,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.18a14", + version="0.8.18", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 07e74e8de4736e57aa4d5dd87f8eedd691082630 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Sat, 3 Feb 2024 23:47:35 +0800 Subject: [PATCH 035/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 4e0635dc8a..7597e1243e 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.18a14" +__version__ = "0.8.18" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From 42caae57c392cd186c2c3eac6de9457f22822935 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Sat, 3 Feb 2024 23:47:48 +0800 Subject: [PATCH 036/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 7597e1243e..4e0635dc8a 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.18" +__version__ = "0.8.18a14" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From 29a29719fdea6d29c6edf6d815e5f623ec94a430 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Sat, 3 Feb 2024 23:48:10 +0800 Subject: [PATCH 037/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index b0efbaa94e..e918ac7264 100644 --- a/python/setup.py +++ b/python/setup.py @@ -114,7 +114,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.18", + version="0.8.18a14", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 65000a9d743d947e78175ec1155fe97506dc72f5 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Sat, 3 Feb 2024 23:48:37 +0800 Subject: [PATCH 038/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index fc10fac235..b0efbaa94e 100644 --- a/python/setup.py +++ b/python/setup.py @@ -114,7 +114,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.18b14", + version="0.8.18", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 7a0ee2480fb29e1ab4b7d048b9be368197ed779a Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Sat, 3 Feb 2024 23:50:18 +0800 Subject: [PATCH 039/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index ccdf28d4cc..7597e1243e 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.18b14" +__version__ = "0.8.18" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From 4f44560beb8a34926344e41a5bd67030ca381483 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Sun, 4 Feb 2024 16:32:12 +0800 Subject: [PATCH 040/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index 4caf252955..08e6e916fe 100644 --- a/python/setup.py +++ b/python/setup.py @@ -114,7 +114,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.19", + version="0.8.19a1", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 023cbdb7db3c2f78e11495156a90fbf085085b23 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Sun, 4 Feb 2024 16:32:31 +0800 Subject: [PATCH 041/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 09f0ca7309..7b758e5966 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.19" +__version__ = "0.8.19a1" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From 2024dff731c340b7171ec2b889601775e17116e9 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Sun, 4 Feb 2024 17:17:34 +0800 Subject: [PATCH 042/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index e5141d15d0..aeed1a4609 100644 --- a/python/setup.py +++ b/python/setup.py @@ -114,7 +114,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.19a2", + version="0.8.20", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 1a4b9e5cf7e2a8caf2f434e6e80ccd48d27b398b Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Sun, 4 Feb 2024 17:17:50 +0800 Subject: [PATCH 043/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 0321560863..d8cd3c982e 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.19a2" +__version__ = "0.8.20" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From 067c5b59ead0a4c434351ad54462550c0288421e Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Sun, 4 Feb 2024 23:50:47 +0800 Subject: [PATCH 044/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index c411b6fd0c..6d59d2ab84 100644 --- a/python/setup.py +++ b/python/setup.py @@ -114,7 +114,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.22a1", + version="0.8.22", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From f1d76cae7ddfeef7665b7af6659765840358c06d Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Sun, 4 Feb 2024 23:51:03 +0800 Subject: [PATCH 045/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 698bc63db7..9ad5bd5374 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.22a1" +__version__ = "0.8.22" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From 2284305a44f2aa9d7107cb91d857695651b99373 Mon Sep 17 00:00:00 2001 From: Zijian Hu Date: Sun, 11 Feb 2024 22:09:11 -0800 Subject: [PATCH 046/135] [train.llm] update README, requirements (cherry picked from commit d5503afc9db4768b947c83373bf1c6627fbbfd84) --- python/examples/train/llm_train/README.md | 93 +++++++++++-------- .../examples/train/llm_train/requirements.txt | 2 +- 2 files changed, 53 insertions(+), 42 deletions(-) diff --git a/python/examples/train/llm_train/README.md b/python/examples/train/llm_train/README.md index d6324da6e4..a06946b658 100644 --- a/python/examples/train/llm_train/README.md +++ b/python/examples/train/llm_train/README.md @@ -2,12 +2,12 @@ FedML logo -# LLM Fine-tune +# LLM Training This repo contains an MLOps-supported training pipeline to help users build their own large language model (LLM) on proprietary/private data. This repo aims to provide a minimalist example of efficient LLM training/fine-tuning -and to illustrate how to use FedML Launch and fine-tuning. +and to illustrate how to use FEDML Launch. We leverage Pythia 7B by default and recently added support for Llama 2. The repo contains: @@ -18,41 +18,16 @@ The repo contains: - Supports [DeepSpeed](https://www.deepspeed.ai/). - Dataset implementation with [datasets](https://huggingface.co/docs/datasets/index). -## How to Use Llama 2 - -Our example uses Pythia by default, but we recently added support for Llama2. -If you'd like to use Llama2, please see the following instructions before getting started. - -To use [Llama 2](https://ai.meta.com/llama/), you need to apply access from Meta and request Meta's private -Hugging Face repo access. - -1. Make sure your `transformers` version is `4.31.0` or newer. You could update your transformers via - `pip install --upgrade transformers`. -2. Please visit the [Meta website](https://ai.meta.com/resources/models-and-libraries/llama-downloads/) and apply for - access. -3. Apply for [Meta's private repo](https://huggingface.co/meta-llama/Llama-2-7b-hf) - on [Hugging Face](https://huggingface.co/meta-llama/Llama-2-7b-hf). See below image for detail. - ![Meta's private repo on Hugging Face](assets/Llama/huggingface_llama_repo.png) -4. Once both access are granted, you can start using Llama by passing `--model_name "meta-llama/Llama-2-7b-hf"` to the training script. - -> **Warning** -> Since Llama 2 is on a private Hugging Face repo, you need to either login to Hugging Face or provide your access token. -> - To login to huggingface (see https://huggingface.co/settings/tokens for detail), run `huggingface-cli login` in - command line. -> - To pass an access token, you need to do one of the following: -> - Set environment variable `HUGGING_FACE_HUB_TOKEN=""` -> - For centralized/conventional training, pass `--auth_token ""` in the command line. - ## Getting Started Clone the repo then go to the project directory: ```shell # clone the repo -git clone https://github.com/FedML-AI/llm-finetune.git +git clone https://github.com/FedML-AI/FedML.git # go to the project directory -cd llm-finetune +cd python/examples/train/llm_train ``` Install dependencies with the following command: @@ -63,7 +38,7 @@ pip install -r requirements.txt See [Dependencies](#dependencies) for more information on the dependency versions. -### Conventional/Centralized Training +### Training The [`run_train.py`](run_train.py) contains a minimal example for conventional/centralized LLM training and fine-tuning on [`databricks-dolly-15k`](https://huggingface.co/datasets/FedML/databricks-dolly-15k-niid) dataset. @@ -84,6 +59,9 @@ bash scripts/train_deepspeed.sh \ ... # additional arguments ``` +> **Note** +> You can use `bash scripts/train.sh -h` to list all the supported CLI options. + > **Note** > If you have an Amper or newer GPU (e.g., RTX 3000 series or newer), you could turn on **bf16** to have more > efficient training by passing `--bf16 "True"` in the command line. @@ -92,20 +70,53 @@ bash scripts/train_deepspeed.sh \ > when using PyTorch DDP with LoRA and gradient checkpointing, you need to turn off `find_unused_parameters` > by passing `--ddp_find_unused_parameters "False"` in the command line. +### Train with FEDML Launch + +If you have trouble finding computing resources, you can launch your training job via [FEDML Launch](https://doc.fedml.ai/launch) and left FEDML to find the most cost-effective resource for your task. + +```shell +# install fedml library +pip3 install fedml + +# launch your training job +fedml launch job.yaml +``` + +You can modify the training command in [job.yaml](job.yaml) by +- specify training settings in `job` section +- specify environment setup settings in `bootstrap` section +- specify compute resources in `computing` section + +## How to Use Llama 2 + +Our example uses Pythia by default, but we recently added support for Llama2. +If you'd like to use Llama2, please see the following instructions before getting started. + +To use [Llama 2](https://ai.meta.com/llama/), you need to apply access from Meta and request Meta's private +Hugging Face repo access. + +1. Make sure your `transformers` version is `4.31.0` or newer. You could update your transformers via + `pip install --upgrade transformers`. +2. Please visit the [Meta website](https://ai.meta.com/resources/models-and-libraries/llama-downloads/) and apply for + access. +3. Apply for [Meta's private repo](https://huggingface.co/meta-llama/Llama-2-7b-hf) + on [Hugging Face](https://huggingface.co/meta-llama/Llama-2-7b-hf). See below image for detail. + ![Meta's private repo on Hugging Face](assets/Llama/huggingface_llama_repo.png) +4. Once both access are granted, you can start using Llama by passing `--model_name "meta-llama/Llama-2-7b-hf"` to the training script. + +> **Warning** +> Since Llama 2 is on a private Hugging Face repo, you need to either login to Hugging Face or provide your access token. +> - To login to huggingface (see https://huggingface.co/settings/tokens for detail), run `huggingface-cli login` in + command line. +> - To pass an access token, you need to do one of the following: +> - Set environment variable `HUGGING_FACE_HUB_TOKEN=""` +> - For centralized/conventional training, pass `--auth_token ""` in the command line. + + ### Dependencies We have tested our implement with the following setup: - Ubuntu `20.04.5 LTS` and `22.04.2 LTS` - CUDA `12.2`, `11.8`, `11.7` and `11.6` -- Python `3.8.13` and `3.9.16` - - `fedml>=0.8.4a7` - - `torch>=2.0.0,<=2.1.0` - - `torchvision>=0.15.1,<=0.16.0` - - `transformers>=4.31.0,<=4.34.0` - - `peft>=0.4.0,<=0.5.0` - - `datasets>=2.11.0,<=2.14.5` - - `deepspeed>=0.9.1,<=0.10.3` - - `numpy>=1.24.3,<=1.24.4` - - `tensorboard>=2.12.2,<=2.13.0` - - `mpi4py>=3.1.4,<=3.1.5` +- Python `3.8.13`, `3.9.16` and `3.10.13` diff --git a/python/examples/train/llm_train/requirements.txt b/python/examples/train/llm_train/requirements.txt index f96ed6a897..7502975cc0 100644 --- a/python/examples/train/llm_train/requirements.txt +++ b/python/examples/train/llm_train/requirements.txt @@ -8,7 +8,7 @@ transformers[torch]>=4.31.0 safetensors datasets>=2.14.0 einops -fedml[llm]>=0.8.17 +fedml[llm]>=0.8.18 tqdm wandb pyyaml From 3d21adb2505a661e328d42d81f02660ced2a7596 Mon Sep 17 00:00:00 2001 From: Zijian Hu Date: Wed, 14 Feb 2024 12:20:20 -0800 Subject: [PATCH 047/135] [train.llm] update flash attention handling during model creation --- python/fedml/train/llm/configurations.py | 75 ++++++++++++++++++------ python/fedml/train/llm/integrations.py | 9 +++ python/setup.py | 2 +- 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/python/fedml/train/llm/configurations.py b/python/fedml/train/llm/configurations.py index 1756bd85f4..7c47519577 100644 --- a/python/fedml/train/llm/configurations.py +++ b/python/fedml/train/llm/configurations.py @@ -22,8 +22,9 @@ PROMPT_STYLES, ) from .dataset_utils import DEFAULT_COLUMN_NAME_MAPPING, DEFAULT_KEYWORD_REPLACEMENTS +from .integrations import is_transformers_greater_or_equal_4_34, is_transformers_greater_or_equal_4_36 from .modeling_utils import get_model_class_from_config -from .typing import ModelType, PeftConfigType, to_torch_dtype +from .typing import ModelConfigType, ModelType, PeftConfigType, to_torch_dtype from .utils import dataclass_to_dict, is_directory, is_file, to_sanitized_dict @@ -252,26 +253,66 @@ def get_model_kwargs(self, **kwargs: Any) -> Dict[str, Any]: ) model_kwargs.update(kwargs) - config = AutoConfig.from_pretrained(**model_kwargs) + config: Optional[ModelConfigType] = model_kwargs.pop("config", None) + if config is None: + config = AutoConfig.from_pretrained(**model_kwargs) model_cls = get_model_class_from_config(config, **model_kwargs) - if compare_versions("transformers", "<", "4.34.0"): - if "use_flash_attention_2" in model_kwargs: - warnings.warn(f"Installed `transformers` does not support `use_flash_attention_2` flag.") - model_kwargs.pop("use_flash_attention_2", False) + # remove flash attention keys and later add relevant keys back + attn_implementation = model_kwargs.pop("attn_implementation", None) - elif getattr(model_cls, "_supports_flash_attn_2", False): - # for `transformers >= 4.34.0`, some huggingface models natively support flash attention v2. - # only enable `use_flash_attention_2` flag for supported models - # see https://github.com/huggingface/transformers/issues/26350 - model_kwargs.setdefault("use_flash_attention_2", self.use_flash_attention) + if ( + model_kwargs.pop("use_flash_attention_2", None) + or attn_implementation == "flash_attention_2" + or self.use_flash_attention + ): + # if enable flash attention + if getattr(model_cls, "_supports_flash_attn_2", False): + # for `transformers >= 4.34.0`, some huggingface models natively support flash attention v2. + # only set `use_flash_attention_2` or `attn_implementation` for supported models + # see https://github.com/huggingface/transformers/issues/26350 + + if is_transformers_greater_or_equal_4_36(): + # `transformers >= 4.36.0` updated flash attention API + model_kwargs["attn_implementation"] = attn_implementation = "flash_attention_2" + elif is_transformers_greater_or_equal_4_34(): + # if `4.34.0 <= transformers < 4.36.0` + model_kwargs["use_flash_attention_2"] = True + attn_implementation = None + + if not self.load_pretrained: + # see https://discuss.huggingface.co/t/how-to-load-model-without-pretrained-weight/34155/3 + # When not loading pretrain weights, need to create model with `AutoModelForCausalLM.from_config` + + # must rebuild config with the updated model kwargs + config: ModelConfigType = AutoConfig.from_pretrained(**model_kwargs) + + if is_transformers_greater_or_equal_4_34() and not is_transformers_greater_or_equal_4_36(): + # For `4.34.0 <= transformers < 4.36.0`, `AutoModel.from_config` does not support + # `use_flash_attention_2` flag. Need to enable manually + config = model_cls._check_and_enable_flash_attn_2( + config, + torch_dtype=model_kwargs["torch_dtype"], + device_map=model_kwargs.get("device_map", None) + ) + + model_kwargs["config"] = config - elif model_kwargs.get("use_flash_attention_2", False): - warnings.warn( - f"Model \"{model_kwargs['pretrained_model_name_or_path']}\" does not natively support flash" - f" attention v2. Setting `use_flash_attention_2 = False`." - ) - model_kwargs["use_flash_attention_2"] = False + else: + if not is_transformers_greater_or_equal_4_34(): + warnings.warn(f"`transformers >= 4.34.0` is required for native flash attention support.") + else: + warnings.warn( + f"Model \"{model_kwargs['pretrained_model_name_or_path']}\" does not natively support flash" + f" attention. Fallback to default options." + ) + + # disable flash attention flags + attn_implementation = None + + # add back `attn_implementation` if needed + if is_transformers_greater_or_equal_4_36() and attn_implementation != "flash_attention_2": + model_kwargs["attn_implementation"] = attn_implementation return model_kwargs diff --git a/python/fedml/train/llm/integrations.py b/python/fedml/train/llm/integrations.py index 0a1a878157..388e41ee4e 100644 --- a/python/fedml/train/llm/integrations.py +++ b/python/fedml/train/llm/integrations.py @@ -1,5 +1,6 @@ import importlib.util +from accelerate.utils import compare_versions from peft.import_utils import is_bnb_available, is_bnb_4bit_available try: @@ -26,3 +27,11 @@ def is_flash_attn_available() -> bool: _fedml_available = _is_package_available("fedml") _flash_attn_available = _is_package_available("flash_attn") + + +def is_transformers_greater_or_equal_4_34() -> bool: + return compare_versions("transformers", ">=", "4.34.0") + + +def is_transformers_greater_or_equal_4_36() -> bool: + return compare_versions("transformers", ">=", "4.36.0") diff --git a/python/setup.py b/python/setup.py index 0bc2f80b9f..d42e5cc409 100644 --- a/python/setup.py +++ b/python/setup.py @@ -92,7 +92,7 @@ def finalize_options(self): ] requirements_extra_llm = [ - "accelerate", + "accelerate>=0.24.0", "peft>=0.4.0", "transformers[torch]>=4.31.0", "datasets>=2.14.0", From 85058e68ad38837f467700e746872009c297222f Mon Sep 17 00:00:00 2001 From: Zijian Hu Date: Wed, 14 Feb 2024 15:06:08 -0800 Subject: [PATCH 048/135] [train.llm] fix falcon loading issue; add `trust_remote_code` CLI option --- python/fedml/train/llm/configurations.py | 13 +++++++++++-- python/fedml/train/llm/modeling_utils.py | 3 +++ python/fedml/train/llm/train_utils.py | 17 ++++------------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/python/fedml/train/llm/configurations.py b/python/fedml/train/llm/configurations.py index 7c47519577..68f8b82510 100644 --- a/python/fedml/train/llm/configurations.py +++ b/python/fedml/train/llm/configurations.py @@ -183,6 +183,15 @@ class ModelArguments: metadata={"help": "Authentication token for Hugging Face private models such as Llama 2."} ) load_pretrained: bool = field(default=True, metadata={"help": "Whether to load pretrained model weights."}) + trust_remote_code: bool = field( + default=False, + metadata={ + "help": "Whether to allow for custom code defined on Hugging Face Hub in their own modeling, configuration," + " tokenization or even pipeline files. This option should only be set to `True` for repositories" + " you trust and in which you have read the code, as it will execute code present on the Hub on your" + " local machine.", + } + ) use_flash_attention: bool = field(default=False, metadata={"help": "Whether to use flash attention."}) use_fast_tokenizer: bool = field( default=True, @@ -249,7 +258,7 @@ def get_model_kwargs(self, **kwargs: Any) -> Dict[str, Any]: pretrained_model_name_or_path=self.model_name_or_path, revision=self.model_revision, torch_dtype=self.torch_dtype, - trust_remote_code=True, + trust_remote_code=self.trust_remote_code, ) model_kwargs.update(kwargs) @@ -323,7 +332,7 @@ def get_tokenizer_kwargs(self, **kwargs: Any) -> Dict[str, Any]: ), revision=self.tokenizer_revision if bool(self.tokenizer_revision) else self.model_revision, use_fast=self.use_fast_tokenizer, - trust_remote_code=True, + trust_remote_code=self.trust_remote_code, ) tokenizer_kwargs.update(kwargs) diff --git a/python/fedml/train/llm/modeling_utils.py b/python/fedml/train/llm/modeling_utils.py index 5d169d2412..3e9ccec54a 100644 --- a/python/fedml/train/llm/modeling_utils.py +++ b/python/fedml/train/llm/modeling_utils.py @@ -218,6 +218,9 @@ def get_model_class_from_config( cls: _BaseAutoModelClass = AutoModelForCausalLM, **kwargs: Any ) -> Type[ModelType]: + # remove redundant keys + kwargs.pop("pretrained_model_name_or_path", None) + trust_remote_code = kwargs.pop("trust_remote_code", None) has_remote_code = hasattr(config, "auto_map") and cls.__name__ in config.auto_map has_local_code = type(config) in cls._model_mapping.keys() diff --git a/python/fedml/train/llm/train_utils.py b/python/fedml/train/llm/train_utils.py index 3918b860bb..2a82424243 100644 --- a/python/fedml/train/llm/train_utils.py +++ b/python/fedml/train/llm/train_utils.py @@ -190,26 +190,17 @@ def get_base_model( **kwargs: Any ) -> ModelType: kwargs = model_args.get_model_kwargs(**kwargs) - use_transformers_flash_attn = kwargs.get("use_flash_attention_2", False) + config: Optional[ModelConfigType] = kwargs.pop("config", None) if model_args.load_pretrained: kwargs.setdefault("low_cpu_mem_usage", not is_deepspeed_zero3_enabled()) model: ModelType = AutoModelForCausalLM.from_pretrained(**kwargs) else: - config: ModelConfigType = AutoConfig.from_pretrained(**kwargs) + if config is None: + config: ModelConfigType = AutoConfig.from_pretrained(**kwargs) torch_dtype: Optional[torch.dtype] = kwargs.get("torch_dtype", model_args.torch_dtype) - if use_transformers_flash_attn: - # As of transformers v4.34.0, `AutoModel.from_config` does not support `use_flash_attention_2` flag - # enable `use_flash_attention_2` manually - model_cls = get_model_class_from_config(config, **kwargs) - config = model_cls._check_and_enable_flash_attn_2( - config, - torch_dtype=torch_dtype, - device_map=kwargs.get("device_map", None) - ) - # see https://discuss.huggingface.co/t/how-to-load-model-without-pretrained-weight/34155/3 model: ModelType = AutoModelForCausalLM.from_config(config, torch_dtype=torch_dtype) @@ -221,7 +212,7 @@ def get_base_model( # model.config should also be updated assert model.config.vocab_size == tokenizer_length - if model_args.use_flash_attention and not use_transformers_flash_attn: + if model_args.use_flash_attention and not getattr(model, "_supports_flash_attn_2", False): # patch models that do not support `use_flash_attention_2` add_flash_attention(model) From 1e3d39c2a184643530e916608db275fdf2d406dc Mon Sep 17 00:00:00 2001 From: Alay Shah Date: Thu, 15 Feb 2024 20:11:05 -0800 Subject: [PATCH 049/135] Update version --- python/fedml/__init__.py | 2 +- python/setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index b2772cb8cd..3e644267ca 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.25a1" +__version__ = "0.8.25a2" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release diff --git a/python/setup.py b/python/setup.py index d42e5cc409..8bae329dc0 100644 --- a/python/setup.py +++ b/python/setup.py @@ -114,7 +114,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.25a1", + version="0.8.25a2", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 5271346f680ddcc3227524622b0a70bd299f66aa Mon Sep 17 00:00:00 2001 From: Alay Shah Date: Wed, 21 Feb 2024 17:11:50 -0800 Subject: [PATCH 050/135] Update version --- python/fedml/__init__.py | 2 +- python/setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 4055997d76..40350694f0 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.25.dev3" +__version__ = "0.8.25.a3" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release diff --git a/python/setup.py b/python/setup.py index cf31c90888..74e1999818 100644 --- a/python/setup.py +++ b/python/setup.py @@ -114,7 +114,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.25.dev3", + version="0.8.25.a3", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 22f655a2aa88f6ca2fe1370642da8cad135af18f Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 22 Feb 2024 21:53:22 +0800 Subject: [PATCH 051/135] rollback and change the run logs. --- python/fedml/__init__.py | 2 +- python/fedml/api/modules/run.py | 8 ++++---- python/setup.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index c9ff0d4cdc..32a6cdcafb 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.24" +__version__ = "0.8.26" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release diff --git a/python/fedml/api/modules/run.py b/python/fedml/api/modules/run.py index 0d3edb85d4..120a964316 100644 --- a/python/fedml/api/modules/run.py +++ b/python/fedml/api/modules/run.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, Optional from fedml.api.modules.utils import authenticate from fedml.computing.scheduler.comm_utils.platform_utils import validate_platform @@ -11,8 +11,8 @@ class RunLogResult(object): - def __init__(self, run_status: str = None, total_log_lines: int = 0, total_log_pages: int = 0, - log_line_list: List[str] = list(), run_logs: FedMLRunLogModelList = None): + def __init__(self, run_status: RunStatus = None, total_log_lines: int = 0, total_log_pages: int = 0, + log_line_list: Optional[List[str]] = None, run_logs: FedMLRunLogModelList = None): self.run_status = run_status self.total_log_lines = total_log_lines self.total_log_pages = total_log_pages @@ -75,7 +75,7 @@ def list_run(run_name: str, run_id: str, platform: str, api_key: str) -> FedMLRu return run_list_obj -def status(run_name: str, run_id: str, platform: str, api_key: str) -> (FedMLRunModelList, RunStatus): +def status(run_name: Optional[str], run_id: str, platform: str, api_key: str) -> (FedMLRunModelList, RunStatus): _authenticate_and_validate_platform(api_key, platform) run_status = None diff --git a/python/setup.py b/python/setup.py index ac69ddec79..7ca6f52ed9 100644 --- a/python/setup.py +++ b/python/setup.py @@ -114,7 +114,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.24", + version="0.8.26", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From e4eef94e1aa35a9f65e38cd5323fe017a7850058 Mon Sep 17 00:00:00 2001 From: Alay Shah Date: Thu, 22 Feb 2024 14:07:53 -0800 Subject: [PATCH 052/135] Bump test version --- python/fedml/__init__.py | 2 +- python/setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index da1ffe2ab7..f242744d91 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.27.dev1" +__version__ = "0.8.27.a1" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release diff --git a/python/setup.py b/python/setup.py index ddba4d5409..a6d0460f61 100644 --- a/python/setup.py +++ b/python/setup.py @@ -114,7 +114,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.27.dev1", + version="0.8.27.a1", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From afcf516d1f69218c6092aa33bdb446e0eb61242c Mon Sep 17 00:00:00 2001 From: Chaoyang He Date: Fri, 1 Mar 2024 01:44:01 -0800 Subject: [PATCH 053/135] avoid remove the endpoint when cannot match GPU resource --- python/fedml/api/modules/launch.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/python/fedml/api/modules/launch.py b/python/fedml/api/modules/launch.py index af295e276e..83761ec86a 100644 --- a/python/fedml/api/modules/launch.py +++ b/python/fedml/api/modules/launch.py @@ -1,3 +1,4 @@ +import logging import os from typing import List @@ -131,12 +132,13 @@ def job( inner_id = run_id if create_run_result.inner_id is None else create_run_result.inner_id - if (result_code == ApiConstants.ERROR_CODE[ApiConstants.LAUNCHED] or - result_code != ApiConstants.ERROR_CODE[ApiConstants.RESOURCE_MATCHED_STATUS_MATCHED]): - if create_run_result.inner_id is not None: - FedMLLaunchManager.get_instance().cleanup_launch(run_id, create_run_result.inner_id) + if result_code == ApiConstants.ERROR_CODE[ApiConstants.LAUNCHED]: return LaunchResult(result_code=result_code, result_message=result_message, run_id=run_id, project_id=project_id, inner_id=inner_id, result_object=create_run_result) + + if result_code != ApiConstants.ERROR_CODE[ApiConstants.RESOURCE_MATCHED_STATUS_MATCHED]: + if create_run_result.inner_id is not None: + logging.info("Job run id {} cannot match GPU resource".format(run_id)) # Run Job run_result = run(create_run_result=create_run_result, api_key=api_key, device_server=device_server, From 6f9f9cc7962c31d1cdeb538b51bbdc0c4f172ff0 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Fri, 1 Mar 2024 17:47:13 +0800 Subject: [PATCH 054/135] Update setup.py --- python/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/setup.py b/python/setup.py index 96a14277c9..6e76852ade 100644 --- a/python/setup.py +++ b/python/setup.py @@ -116,7 +116,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.27a3", + version="0.8.27a4", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From c9774a9232fe51427e69456214498f1560cf4fb0 Mon Sep 17 00:00:00 2001 From: Alex <98797487+fedml-alex@users.noreply.github.com> Date: Fri, 1 Mar 2024 17:47:36 +0800 Subject: [PATCH 055/135] Update __init__.py --- python/fedml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 1e84b5b49c..8818bf140f 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.27a3" +__version__ = "0.8.27a4" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release From 50601a87ca26462bd2d3749224dd14786903be39 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 2 Mar 2024 15:55:01 +0800 Subject: [PATCH 056/135] [CoreEngine] 1. fix the issue which the gpu id is not released into the local redis when deleting the endpoint. 2. report the realtime gpu available count to mlops, not from the local redis cache. --- python/fedml/__init__.py | 2 +- python/fedml/computing/scheduler/comm_utils/job_utils.py | 4 ++-- .../scheduler/scheduler_core/compute_gpu_cache.py | 2 ++ python/fedml/core/mlops/mlops_device_perfs.py | 7 +++++-- python/setup.py | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index b06c6264a7..2079f681d4 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.27.dev2" +__version__ = "0.8.27.dev5" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release diff --git a/python/fedml/computing/scheduler/comm_utils/job_utils.py b/python/fedml/computing/scheduler/comm_utils/job_utils.py index 3e994640e9..d8dd8e00b7 100644 --- a/python/fedml/computing/scheduler/comm_utils/job_utils.py +++ b/python/fedml/computing/scheduler/comm_utils/job_utils.py @@ -147,7 +147,7 @@ def request_gpu_ids(request_gpu_num, available_gpu_ids): request_gpu_num = 0 if request_gpu_num is None else request_gpu_num matched_gpu_num = min(available_gpu_count, request_gpu_num) if matched_gpu_num <= 0 or matched_gpu_num != request_gpu_num: - return None, None, None + return None, None matched_gpu_ids = map(lambda x: str(x), available_gpu_ids[0:matched_gpu_num]) cuda_visible_gpu_ids_str = ",".join(matched_gpu_ids) @@ -195,7 +195,7 @@ def release_gpu_ids(self, run_id, device_id): ComputeCacheManager.get_instance().get_gpu_cache().get_device_lock_key(edge_device_id) ): available_gpu_ids = ComputeCacheManager.get_instance().get_gpu_cache().get_device_available_gpu_ids( - device_id) + edge_device_id) available_gpu_ids.extend(run_gpu_ids.copy()) available_gpu_ids = list(dict.fromkeys(available_gpu_ids)) ComputeCacheManager.get_instance().get_gpu_cache().set_device_available_gpu_ids( diff --git a/python/fedml/computing/scheduler/scheduler_core/compute_gpu_cache.py b/python/fedml/computing/scheduler/scheduler_core/compute_gpu_cache.py index 5bb7e91f10..6bc503eb6e 100755 --- a/python/fedml/computing/scheduler/scheduler_core/compute_gpu_cache.py +++ b/python/fedml/computing/scheduler/scheduler_core/compute_gpu_cache.py @@ -87,6 +87,8 @@ def get_device_available_gpu_ids(self, device_id): if device_available_gpu_ids is not None and str(device_available_gpu_ids).strip() != "": device_available_gpu_ids = device_available_gpu_ids.split(',') device_available_gpu_ids = self.map_str_list_to_int_list(device_available_gpu_ids) + else: + return [] return device_available_gpu_ids diff --git a/python/fedml/core/mlops/mlops_device_perfs.py b/python/fedml/core/mlops/mlops_device_perfs.py index d488ef27a4..273046217a 100644 --- a/python/fedml/core/mlops/mlops_device_perfs.py +++ b/python/fedml/core/mlops/mlops_device_perfs.py @@ -167,8 +167,11 @@ def report_gpu_device_info(edge_id, mqtt_mgr=None): topic_name = "ml_client/mlops/gpu_device_info" - gpu_available_ids = JobRunnerUtils.get_available_gpu_id_list(edge_id) - gpu_available_ids = JobRunnerUtils.trim_unavailable_gpu_ids(gpu_available_ids) + # We should report realtime available gpu count to MLOps, not from local redis cache. + # Use gpu_available_ids from sys_utils.get_sys_realtime_stats() + # Do not use the following two lines as the realtime available gpu ids. + # gpu_available_ids = JobRunnerUtils.get_available_gpu_id_list(edge_id) + # gpu_available_ids = JobRunnerUtils.trim_unavailable_gpu_ids(gpu_available_ids) gpu_cores_available = len(gpu_available_ids) deploy_worker_id_list = list() try: diff --git a/python/setup.py b/python/setup.py index a9d61b352a..36fa912e50 100644 --- a/python/setup.py +++ b/python/setup.py @@ -116,7 +116,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.27.dev2", + version="0.8.27.dev5", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 3c93f439b2ceb285d04172f3d4da2a08412e6683 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 2 Mar 2024 18:42:03 +0800 Subject: [PATCH 057/135] [Monitor] remove the not accurate status checking for initializing and deploying. --- python/fedml/__init__.py | 2 +- .../scheduler/comm_utils/job_monitor.py | 26 ------------------- python/setup.py | 2 +- 3 files changed, 2 insertions(+), 28 deletions(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 2079f681d4..aef492b5f4 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.27.dev5" +__version__ = "0.8.27.dev6" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release diff --git a/python/fedml/computing/scheduler/comm_utils/job_monitor.py b/python/fedml/computing/scheduler/comm_utils/job_monitor.py index 59f6c32bef..3fdd856ca9 100644 --- a/python/fedml/computing/scheduler/comm_utils/job_monitor.py +++ b/python/fedml/computing/scheduler/comm_utils/job_monitor.py @@ -650,32 +650,6 @@ def monitor_master_endpoint_status(self): except Exception as e: print(f"[Master][{job.job_id}] Exception when check endpoint status: " f"{traceback.format_exc()}") - elif endpoint_status == \ - device_server_constants.ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_INITIALIZING: - started_time = int(float(job.started_time)) - timeout = time.time() - started_time - if timeout > SchedulerConstants.ENDPOINT_DEPLOYMENT_PROVISIONING_TIMEOUT: - print(f"[Master][{job.job_id}] Due to timeout, set endpoint status to " - f"offline at the status {endpoint_status}.") - mlops.log_endpoint_status( - job.job_id, - device_server_constants.ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED) - FedMLModelCache.get_instance().set_end_point_status( - job.job_id, endpoint_name, - device_server_constants.ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED) - elif endpoint_status == \ - device_server_constants.ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYING: - started_time = int(float(job.started_time)) - timeout = time.time() - started_time - if timeout > SchedulerConstants.ENDPOINT_DEPLOYMENT_DEPLOYING_TIMEOUT: - print(f"[Master][{job.job_id}] Due to timeout, set endpoint status to " - f"offline at the status {endpoint_status}.") - mlops.log_endpoint_status( - job.job_id, - device_server_constants.ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED) - FedMLModelCache.get_instance().set_end_point_status( - job.job_id, endpoint_name, - device_server_constants.ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED) elif endpoint_status == device_server_constants.ServerConstants.MSG_MLOPS_SERVER_STATUS_OFFLINE: # If the endpoint is offline, then report offline status to the MLOps. model_config_parameters = model_config.get("parameters", {}) diff --git a/python/setup.py b/python/setup.py index 36fa912e50..e9b74f9616 100644 --- a/python/setup.py +++ b/python/setup.py @@ -116,7 +116,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.27.dev5", + version="0.8.27.dev6", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 97ac2b4265e19a05207d1e292f43b7239d2f28e1 Mon Sep 17 00:00:00 2001 From: Zijian Hu Date: Sun, 11 Feb 2024 22:09:11 -0800 Subject: [PATCH 058/135] [train.llm] update README, requirements (cherry picked from commit d5503afc9db4768b947c83373bf1c6627fbbfd84) --- python/examples/train/llm_train/README.md | 93 +++++++++++-------- .../examples/train/llm_train/requirements.txt | 2 +- 2 files changed, 53 insertions(+), 42 deletions(-) diff --git a/python/examples/train/llm_train/README.md b/python/examples/train/llm_train/README.md index d6324da6e4..a06946b658 100644 --- a/python/examples/train/llm_train/README.md +++ b/python/examples/train/llm_train/README.md @@ -2,12 +2,12 @@ FedML logo -# LLM Fine-tune +# LLM Training This repo contains an MLOps-supported training pipeline to help users build their own large language model (LLM) on proprietary/private data. This repo aims to provide a minimalist example of efficient LLM training/fine-tuning -and to illustrate how to use FedML Launch and fine-tuning. +and to illustrate how to use FEDML Launch. We leverage Pythia 7B by default and recently added support for Llama 2. The repo contains: @@ -18,41 +18,16 @@ The repo contains: - Supports [DeepSpeed](https://www.deepspeed.ai/). - Dataset implementation with [datasets](https://huggingface.co/docs/datasets/index). -## How to Use Llama 2 - -Our example uses Pythia by default, but we recently added support for Llama2. -If you'd like to use Llama2, please see the following instructions before getting started. - -To use [Llama 2](https://ai.meta.com/llama/), you need to apply access from Meta and request Meta's private -Hugging Face repo access. - -1. Make sure your `transformers` version is `4.31.0` or newer. You could update your transformers via - `pip install --upgrade transformers`. -2. Please visit the [Meta website](https://ai.meta.com/resources/models-and-libraries/llama-downloads/) and apply for - access. -3. Apply for [Meta's private repo](https://huggingface.co/meta-llama/Llama-2-7b-hf) - on [Hugging Face](https://huggingface.co/meta-llama/Llama-2-7b-hf). See below image for detail. - ![Meta's private repo on Hugging Face](assets/Llama/huggingface_llama_repo.png) -4. Once both access are granted, you can start using Llama by passing `--model_name "meta-llama/Llama-2-7b-hf"` to the training script. - -> **Warning** -> Since Llama 2 is on a private Hugging Face repo, you need to either login to Hugging Face or provide your access token. -> - To login to huggingface (see https://huggingface.co/settings/tokens for detail), run `huggingface-cli login` in - command line. -> - To pass an access token, you need to do one of the following: -> - Set environment variable `HUGGING_FACE_HUB_TOKEN=""` -> - For centralized/conventional training, pass `--auth_token ""` in the command line. - ## Getting Started Clone the repo then go to the project directory: ```shell # clone the repo -git clone https://github.com/FedML-AI/llm-finetune.git +git clone https://github.com/FedML-AI/FedML.git # go to the project directory -cd llm-finetune +cd python/examples/train/llm_train ``` Install dependencies with the following command: @@ -63,7 +38,7 @@ pip install -r requirements.txt See [Dependencies](#dependencies) for more information on the dependency versions. -### Conventional/Centralized Training +### Training The [`run_train.py`](run_train.py) contains a minimal example for conventional/centralized LLM training and fine-tuning on [`databricks-dolly-15k`](https://huggingface.co/datasets/FedML/databricks-dolly-15k-niid) dataset. @@ -84,6 +59,9 @@ bash scripts/train_deepspeed.sh \ ... # additional arguments ``` +> **Note** +> You can use `bash scripts/train.sh -h` to list all the supported CLI options. + > **Note** > If you have an Amper or newer GPU (e.g., RTX 3000 series or newer), you could turn on **bf16** to have more > efficient training by passing `--bf16 "True"` in the command line. @@ -92,20 +70,53 @@ bash scripts/train_deepspeed.sh \ > when using PyTorch DDP with LoRA and gradient checkpointing, you need to turn off `find_unused_parameters` > by passing `--ddp_find_unused_parameters "False"` in the command line. +### Train with FEDML Launch + +If you have trouble finding computing resources, you can launch your training job via [FEDML Launch](https://doc.fedml.ai/launch) and left FEDML to find the most cost-effective resource for your task. + +```shell +# install fedml library +pip3 install fedml + +# launch your training job +fedml launch job.yaml +``` + +You can modify the training command in [job.yaml](job.yaml) by +- specify training settings in `job` section +- specify environment setup settings in `bootstrap` section +- specify compute resources in `computing` section + +## How to Use Llama 2 + +Our example uses Pythia by default, but we recently added support for Llama2. +If you'd like to use Llama2, please see the following instructions before getting started. + +To use [Llama 2](https://ai.meta.com/llama/), you need to apply access from Meta and request Meta's private +Hugging Face repo access. + +1. Make sure your `transformers` version is `4.31.0` or newer. You could update your transformers via + `pip install --upgrade transformers`. +2. Please visit the [Meta website](https://ai.meta.com/resources/models-and-libraries/llama-downloads/) and apply for + access. +3. Apply for [Meta's private repo](https://huggingface.co/meta-llama/Llama-2-7b-hf) + on [Hugging Face](https://huggingface.co/meta-llama/Llama-2-7b-hf). See below image for detail. + ![Meta's private repo on Hugging Face](assets/Llama/huggingface_llama_repo.png) +4. Once both access are granted, you can start using Llama by passing `--model_name "meta-llama/Llama-2-7b-hf"` to the training script. + +> **Warning** +> Since Llama 2 is on a private Hugging Face repo, you need to either login to Hugging Face or provide your access token. +> - To login to huggingface (see https://huggingface.co/settings/tokens for detail), run `huggingface-cli login` in + command line. +> - To pass an access token, you need to do one of the following: +> - Set environment variable `HUGGING_FACE_HUB_TOKEN=""` +> - For centralized/conventional training, pass `--auth_token ""` in the command line. + + ### Dependencies We have tested our implement with the following setup: - Ubuntu `20.04.5 LTS` and `22.04.2 LTS` - CUDA `12.2`, `11.8`, `11.7` and `11.6` -- Python `3.8.13` and `3.9.16` - - `fedml>=0.8.4a7` - - `torch>=2.0.0,<=2.1.0` - - `torchvision>=0.15.1,<=0.16.0` - - `transformers>=4.31.0,<=4.34.0` - - `peft>=0.4.0,<=0.5.0` - - `datasets>=2.11.0,<=2.14.5` - - `deepspeed>=0.9.1,<=0.10.3` - - `numpy>=1.24.3,<=1.24.4` - - `tensorboard>=2.12.2,<=2.13.0` - - `mpi4py>=3.1.4,<=3.1.5` +- Python `3.8.13`, `3.9.16` and `3.10.13` diff --git a/python/examples/train/llm_train/requirements.txt b/python/examples/train/llm_train/requirements.txt index f96ed6a897..7502975cc0 100644 --- a/python/examples/train/llm_train/requirements.txt +++ b/python/examples/train/llm_train/requirements.txt @@ -8,7 +8,7 @@ transformers[torch]>=4.31.0 safetensors datasets>=2.14.0 einops -fedml[llm]>=0.8.17 +fedml[llm]>=0.8.18 tqdm wandb pyyaml From 12d131d7328ab7a2f7f6fc9f78bc1a80ea541820 Mon Sep 17 00:00:00 2001 From: Zijian Hu Date: Wed, 14 Feb 2024 12:20:20 -0800 Subject: [PATCH 059/135] [train.llm] update flash attention handling during model creation --- python/fedml/train/llm/configurations.py | 75 ++++++++++++++++++------ python/fedml/train/llm/integrations.py | 9 +++ python/setup.py | 2 +- 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/python/fedml/train/llm/configurations.py b/python/fedml/train/llm/configurations.py index 1756bd85f4..7c47519577 100644 --- a/python/fedml/train/llm/configurations.py +++ b/python/fedml/train/llm/configurations.py @@ -22,8 +22,9 @@ PROMPT_STYLES, ) from .dataset_utils import DEFAULT_COLUMN_NAME_MAPPING, DEFAULT_KEYWORD_REPLACEMENTS +from .integrations import is_transformers_greater_or_equal_4_34, is_transformers_greater_or_equal_4_36 from .modeling_utils import get_model_class_from_config -from .typing import ModelType, PeftConfigType, to_torch_dtype +from .typing import ModelConfigType, ModelType, PeftConfigType, to_torch_dtype from .utils import dataclass_to_dict, is_directory, is_file, to_sanitized_dict @@ -252,26 +253,66 @@ def get_model_kwargs(self, **kwargs: Any) -> Dict[str, Any]: ) model_kwargs.update(kwargs) - config = AutoConfig.from_pretrained(**model_kwargs) + config: Optional[ModelConfigType] = model_kwargs.pop("config", None) + if config is None: + config = AutoConfig.from_pretrained(**model_kwargs) model_cls = get_model_class_from_config(config, **model_kwargs) - if compare_versions("transformers", "<", "4.34.0"): - if "use_flash_attention_2" in model_kwargs: - warnings.warn(f"Installed `transformers` does not support `use_flash_attention_2` flag.") - model_kwargs.pop("use_flash_attention_2", False) + # remove flash attention keys and later add relevant keys back + attn_implementation = model_kwargs.pop("attn_implementation", None) - elif getattr(model_cls, "_supports_flash_attn_2", False): - # for `transformers >= 4.34.0`, some huggingface models natively support flash attention v2. - # only enable `use_flash_attention_2` flag for supported models - # see https://github.com/huggingface/transformers/issues/26350 - model_kwargs.setdefault("use_flash_attention_2", self.use_flash_attention) + if ( + model_kwargs.pop("use_flash_attention_2", None) + or attn_implementation == "flash_attention_2" + or self.use_flash_attention + ): + # if enable flash attention + if getattr(model_cls, "_supports_flash_attn_2", False): + # for `transformers >= 4.34.0`, some huggingface models natively support flash attention v2. + # only set `use_flash_attention_2` or `attn_implementation` for supported models + # see https://github.com/huggingface/transformers/issues/26350 + + if is_transformers_greater_or_equal_4_36(): + # `transformers >= 4.36.0` updated flash attention API + model_kwargs["attn_implementation"] = attn_implementation = "flash_attention_2" + elif is_transformers_greater_or_equal_4_34(): + # if `4.34.0 <= transformers < 4.36.0` + model_kwargs["use_flash_attention_2"] = True + attn_implementation = None + + if not self.load_pretrained: + # see https://discuss.huggingface.co/t/how-to-load-model-without-pretrained-weight/34155/3 + # When not loading pretrain weights, need to create model with `AutoModelForCausalLM.from_config` + + # must rebuild config with the updated model kwargs + config: ModelConfigType = AutoConfig.from_pretrained(**model_kwargs) + + if is_transformers_greater_or_equal_4_34() and not is_transformers_greater_or_equal_4_36(): + # For `4.34.0 <= transformers < 4.36.0`, `AutoModel.from_config` does not support + # `use_flash_attention_2` flag. Need to enable manually + config = model_cls._check_and_enable_flash_attn_2( + config, + torch_dtype=model_kwargs["torch_dtype"], + device_map=model_kwargs.get("device_map", None) + ) + + model_kwargs["config"] = config - elif model_kwargs.get("use_flash_attention_2", False): - warnings.warn( - f"Model \"{model_kwargs['pretrained_model_name_or_path']}\" does not natively support flash" - f" attention v2. Setting `use_flash_attention_2 = False`." - ) - model_kwargs["use_flash_attention_2"] = False + else: + if not is_transformers_greater_or_equal_4_34(): + warnings.warn(f"`transformers >= 4.34.0` is required for native flash attention support.") + else: + warnings.warn( + f"Model \"{model_kwargs['pretrained_model_name_or_path']}\" does not natively support flash" + f" attention. Fallback to default options." + ) + + # disable flash attention flags + attn_implementation = None + + # add back `attn_implementation` if needed + if is_transformers_greater_or_equal_4_36() and attn_implementation != "flash_attention_2": + model_kwargs["attn_implementation"] = attn_implementation return model_kwargs diff --git a/python/fedml/train/llm/integrations.py b/python/fedml/train/llm/integrations.py index 0a1a878157..388e41ee4e 100644 --- a/python/fedml/train/llm/integrations.py +++ b/python/fedml/train/llm/integrations.py @@ -1,5 +1,6 @@ import importlib.util +from accelerate.utils import compare_versions from peft.import_utils import is_bnb_available, is_bnb_4bit_available try: @@ -26,3 +27,11 @@ def is_flash_attn_available() -> bool: _fedml_available = _is_package_available("fedml") _flash_attn_available = _is_package_available("flash_attn") + + +def is_transformers_greater_or_equal_4_34() -> bool: + return compare_versions("transformers", ">=", "4.34.0") + + +def is_transformers_greater_or_equal_4_36() -> bool: + return compare_versions("transformers", ">=", "4.36.0") diff --git a/python/setup.py b/python/setup.py index e9b74f9616..e2790e3460 100644 --- a/python/setup.py +++ b/python/setup.py @@ -94,7 +94,7 @@ def finalize_options(self): ] requirements_extra_llm = [ - "accelerate", + "accelerate>=0.24.0", "peft>=0.4.0", "transformers[torch]>=4.31.0", "datasets>=2.14.0", From 364937e3276014b0d6c717920fd78f4663e0c77c Mon Sep 17 00:00:00 2001 From: Zijian Hu Date: Wed, 14 Feb 2024 15:06:08 -0800 Subject: [PATCH 060/135] [train.llm] fix falcon loading issue; add `trust_remote_code` CLI option --- python/fedml/train/llm/configurations.py | 13 +++++++++++-- python/fedml/train/llm/modeling_utils.py | 3 +++ python/fedml/train/llm/train_utils.py | 17 ++++------------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/python/fedml/train/llm/configurations.py b/python/fedml/train/llm/configurations.py index 7c47519577..68f8b82510 100644 --- a/python/fedml/train/llm/configurations.py +++ b/python/fedml/train/llm/configurations.py @@ -183,6 +183,15 @@ class ModelArguments: metadata={"help": "Authentication token for Hugging Face private models such as Llama 2."} ) load_pretrained: bool = field(default=True, metadata={"help": "Whether to load pretrained model weights."}) + trust_remote_code: bool = field( + default=False, + metadata={ + "help": "Whether to allow for custom code defined on Hugging Face Hub in their own modeling, configuration," + " tokenization or even pipeline files. This option should only be set to `True` for repositories" + " you trust and in which you have read the code, as it will execute code present on the Hub on your" + " local machine.", + } + ) use_flash_attention: bool = field(default=False, metadata={"help": "Whether to use flash attention."}) use_fast_tokenizer: bool = field( default=True, @@ -249,7 +258,7 @@ def get_model_kwargs(self, **kwargs: Any) -> Dict[str, Any]: pretrained_model_name_or_path=self.model_name_or_path, revision=self.model_revision, torch_dtype=self.torch_dtype, - trust_remote_code=True, + trust_remote_code=self.trust_remote_code, ) model_kwargs.update(kwargs) @@ -323,7 +332,7 @@ def get_tokenizer_kwargs(self, **kwargs: Any) -> Dict[str, Any]: ), revision=self.tokenizer_revision if bool(self.tokenizer_revision) else self.model_revision, use_fast=self.use_fast_tokenizer, - trust_remote_code=True, + trust_remote_code=self.trust_remote_code, ) tokenizer_kwargs.update(kwargs) diff --git a/python/fedml/train/llm/modeling_utils.py b/python/fedml/train/llm/modeling_utils.py index 5d169d2412..3e9ccec54a 100644 --- a/python/fedml/train/llm/modeling_utils.py +++ b/python/fedml/train/llm/modeling_utils.py @@ -218,6 +218,9 @@ def get_model_class_from_config( cls: _BaseAutoModelClass = AutoModelForCausalLM, **kwargs: Any ) -> Type[ModelType]: + # remove redundant keys + kwargs.pop("pretrained_model_name_or_path", None) + trust_remote_code = kwargs.pop("trust_remote_code", None) has_remote_code = hasattr(config, "auto_map") and cls.__name__ in config.auto_map has_local_code = type(config) in cls._model_mapping.keys() diff --git a/python/fedml/train/llm/train_utils.py b/python/fedml/train/llm/train_utils.py index 3918b860bb..2a82424243 100644 --- a/python/fedml/train/llm/train_utils.py +++ b/python/fedml/train/llm/train_utils.py @@ -190,26 +190,17 @@ def get_base_model( **kwargs: Any ) -> ModelType: kwargs = model_args.get_model_kwargs(**kwargs) - use_transformers_flash_attn = kwargs.get("use_flash_attention_2", False) + config: Optional[ModelConfigType] = kwargs.pop("config", None) if model_args.load_pretrained: kwargs.setdefault("low_cpu_mem_usage", not is_deepspeed_zero3_enabled()) model: ModelType = AutoModelForCausalLM.from_pretrained(**kwargs) else: - config: ModelConfigType = AutoConfig.from_pretrained(**kwargs) + if config is None: + config: ModelConfigType = AutoConfig.from_pretrained(**kwargs) torch_dtype: Optional[torch.dtype] = kwargs.get("torch_dtype", model_args.torch_dtype) - if use_transformers_flash_attn: - # As of transformers v4.34.0, `AutoModel.from_config` does not support `use_flash_attention_2` flag - # enable `use_flash_attention_2` manually - model_cls = get_model_class_from_config(config, **kwargs) - config = model_cls._check_and_enable_flash_attn_2( - config, - torch_dtype=torch_dtype, - device_map=kwargs.get("device_map", None) - ) - # see https://discuss.huggingface.co/t/how-to-load-model-without-pretrained-weight/34155/3 model: ModelType = AutoModelForCausalLM.from_config(config, torch_dtype=torch_dtype) @@ -221,7 +212,7 @@ def get_base_model( # model.config should also be updated assert model.config.vocab_size == tokenizer_length - if model_args.use_flash_attention and not use_transformers_flash_attn: + if model_args.use_flash_attention and not getattr(model, "_supports_flash_attn_2", False): # patch models that do not support `use_flash_attention_2` add_flash_attention(model) From 857691feeffeb144202d4d513480d3510d41f219 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 6 Mar 2024 13:27:45 +0800 Subject: [PATCH 061/135] [CoreEngine] 1. report the starting status when received the train message. 2. fixed the issue when message center stopped. --- python/fedml/computing/scheduler/master/server_runner.py | 6 ++++++ .../computing/scheduler/scheduler_core/message_center.py | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/python/fedml/computing/scheduler/master/server_runner.py b/python/fedml/computing/scheduler/master/server_runner.py index 0442c99972..b72878d65e 100755 --- a/python/fedml/computing/scheduler/master/server_runner.py +++ b/python/fedml/computing/scheduler/master/server_runner.py @@ -1567,6 +1567,12 @@ def callback_start_train(self, topic=None, payload=None): if not self.run_as_cloud_agent and not self.run_as_cloud_server: self.ota_upgrade(payload, request_json) + # report server running status + if not self.run_as_cloud_server: + self.mlops_metrics.report_server_id_status( + run_id, ServerConstants.MSG_MLOPS_SERVER_STATUS_STARTING, edge_id=self.edge_id, + server_id=self.edge_id, server_agent_id=self.edge_id) + self.start_request_json = payload self.run_id = run_id ServerConstants.save_runner_infos(self.args.device_id + "." + self.args.os_name, self.edge_id, run_id=run_id) diff --git a/python/fedml/computing/scheduler/scheduler_core/message_center.py b/python/fedml/computing/scheduler/scheduler_core/message_center.py index c7af555a99..2148b0c5ef 100755 --- a/python/fedml/computing/scheduler/scheduler_core/message_center.py +++ b/python/fedml/computing/scheduler/scheduler_core/message_center.py @@ -130,7 +130,7 @@ def stop(self): def check_message_stop_event(self): if self.message_event is not None and self.message_event.is_set(): logging.info("Received message center stopping event.") - raise Exception("Message center stopped (for sender)") + raise MessageCenterStoppedException("Message center stopped (for sender)") def send_message(self, topic, payload, run_id=None): message_entity = FedMLMessageEntity(topic=topic, payload=payload, run_id=run_id) @@ -231,7 +231,7 @@ def start_listener(self, sender_message_queue=None, agent_config=None): def check_listener_message_stop_event(self): if self.listener_message_event is not None and self.listener_message_event.is_set(): logging.info("Received listener message center stopping event.") - raise Exception("Message center stopped (for listener)") + raise MessageCenterStoppedException("Message center stopped (for listener)") def listener_message_dispatch_center(self, topic, payload): self.receive_message_json(topic, payload) From 61312d5b9112dc2e9de7dd90d57ea57ab3e5d6ff Mon Sep 17 00:00:00 2001 From: Chaoyang He Date: Wed, 6 Mar 2024 01:34:59 -0800 Subject: [PATCH 062/135] add handshaking protocol for model deployment --- .../scheduler/master/server_runner.py | 4 +- .../scheduler/slave/client_runner.py | 63 +++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/python/fedml/computing/scheduler/master/server_runner.py b/python/fedml/computing/scheduler/master/server_runner.py index b72878d65e..4906da7faf 100755 --- a/python/fedml/computing/scheduler/master/server_runner.py +++ b/python/fedml/computing/scheduler/master/server_runner.py @@ -2327,7 +2327,7 @@ def callback_request_device_info_from_mlops(self, topic, payload): self.response_device_info_to_mlops(topic, payload) def response_device_info_to_mlops(self, topic, payload): - response_topic = f"master_agent/mlops/response_device_info" + response_topic = f"deploy/master_agent/mlops/response_device_info" payload_json = json.loads(payload) need_gpu_info = payload_json.get("need_gpu_info", False) if self.mlops_metrics is not None: @@ -2601,7 +2601,7 @@ def on_agent_mqtt_connected(self, mqtt_client_object): self.mqtt_mgr.add_message_listener(topic_response_device_info, self.listener_message_dispatch_center) # Setup MQTT message listener to request device info from MLOps. - topic_request_device_info_from_mlops = f"mlops/master_agent/request_device_info/{self.edge_id}" + topic_request_device_info_from_mlops = f"deploy/mlops/master_agent/request_device_info/{self.edge_id}" self.add_message_listener(topic_request_device_info_from_mlops, self.callback_request_device_info_from_mlops) self.mqtt_mgr.add_message_listener( topic_request_device_info_from_mlops, self.listener_message_dispatch_center) diff --git a/python/fedml/computing/scheduler/slave/client_runner.py b/python/fedml/computing/scheduler/slave/client_runner.py index aac57d2174..e06416168c 100755 --- a/python/fedml/computing/scheduler/slave/client_runner.py +++ b/python/fedml/computing/scheduler/slave/client_runner.py @@ -1174,6 +1174,65 @@ def get_all_run_process_list_map(self): return run_process_dict + def response_device_info_to_mlops(self, topic, payload): + payload_json = json.loads(payload) + server_id = payload_json.get("server_id", 0) + run_id = payload_json.get("run_id", 0) + listen_edge_id = str(topic).split("/")[-1] + context = payload_json.get("context", None) + need_gpu_info = payload_json.get("need_gpu_info", False) + need_running_process_list = payload_json.get("need_running_process_list", False) + response_topic = f"deploy/slave_agent/mlops/response_device_info" + if self.mlops_metrics is not None and self.model_device_client_edge_id_list is not None and \ + self.model_device_server_id is not None: + if not need_gpu_info: + device_info_json = { + "edge_id": listen_edge_id, + "fedml_version": fedml.__version__, + "user_id": self.args.user + } + else: + total_mem, free_mem, total_disk_size, free_disk_size, cup_utilization, cpu_cores, gpu_cores_total, \ + gpu_cores_available, sent_bytes, recv_bytes, gpu_available_ids = sys_utils.get_sys_realtime_stats() + host_ip = sys_utils.get_host_ip() + host_port = sys_utils.get_available_port() + gpu_available_ids = JobRunnerUtils.get_available_gpu_id_list(self.edge_id) + gpu_available_ids = JobRunnerUtils.trim_unavailable_gpu_ids(gpu_available_ids) + gpu_cores_available = len(gpu_available_ids) + gpu_list = sys_utils.get_gpu_list() + device_info_json = { + "edge_id": listen_edge_id, + "memoryTotal": round(total_mem * MLOpsUtils.BYTES_TO_GB, 2), + "memoryAvailable": round(free_mem * MLOpsUtils.BYTES_TO_GB, 2), + "diskSpaceTotal": round(total_disk_size * MLOpsUtils.BYTES_TO_GB, 2), + "diskSpaceAvailable": round(free_disk_size * MLOpsUtils.BYTES_TO_GB, 2), + "cpuUtilization": round(cup_utilization, 2), + "cpuCores": cpu_cores, + "gpuCoresTotal": gpu_cores_total, + "gpuCoresAvailable": gpu_cores_available, + "gpu_available_ids": gpu_available_ids, + "gpu_list": gpu_list, + "node_ip": host_ip, + "node_port": host_port, + "networkTraffic": sent_bytes + recv_bytes, + "updateTime": int(MLOpsUtils.get_ntp_time()), + "fedml_version": fedml.__version__, + "user_id": self.args.user + } + if need_running_process_list: + device_info_json["run_process_list_map"] = self.get_all_run_process_list_map() + salve_device_ids = list() + for model_client_edge_id in self.model_device_client_edge_id_list: + salve_device_ids.append(model_client_edge_id) + response_payload = {"slave_device_id": self.model_device_client_edge_id_list[0], + "slave_device_id_list": salve_device_ids, + "master_device_id": self.model_device_server_id, + "run_id": run_id, "edge_id": listen_edge_id, + "edge_info": device_info_json} + if context is not None: + response_payload["context"] = context + self.message_center.send_message(response_topic, json.dumps(response_payload), run_id=run_id) + def callback_report_device_info(self, topic, payload): payload_json = json.loads(payload) server_id = payload_json.get("server_id", 0) @@ -1511,6 +1570,10 @@ def on_agent_mqtt_connected(self, mqtt_client_object): self.add_message_listener(topic_request_device_info, self.callback_report_device_info) self.mqtt_mgr.add_message_listener(topic_request_device_info, self.listener_message_dispatch_center) + topic_request_device_info_from_mlops = f"deploy/mlops/client_agent/request_device_info/{self.edge_id}" + self.add_message_listener(topic_request_device_info_from_mlops, self.response_device_info_to_mlops) + self.mqtt_mgr.add_message_listener(topic_request_device_info_from_mlops, self.listener_message_dispatch_center) + # Setup MQTT message listener to logout from MLOps. topic_client_logout = "mlops/client/logout/" + str(self.edge_id) self.add_message_listener(topic_client_logout, self.callback_client_logout) From 3ad6ef86be92cf3e56280a471373a6f47de7262f Mon Sep 17 00:00:00 2001 From: Alay Shah Date: Sat, 9 Mar 2024 15:07:01 -0800 Subject: [PATCH 063/135] Enhance Build Package --- .../launch/train_build_package/train.py | 267 ------------------ .../launch/train_build_package/train_job.yaml | 9 +- python/fedml/api/modules/federate.py | 5 +- python/fedml/api/modules/train.py | 13 +- .../scheduler/comm_utils/sys_utils.py | 32 +++ .../scheduler/scheduler_entry/constants.py | 2 +- .../scheduler_entry/launch_manager.py | 18 +- 7 files changed, 57 insertions(+), 289 deletions(-) delete mode 100644 python/examples/launch/train_build_package/train.py diff --git a/python/examples/launch/train_build_package/train.py b/python/examples/launch/train_build_package/train.py deleted file mode 100644 index 11f6d8edc6..0000000000 --- a/python/examples/launch/train_build_package/train.py +++ /dev/null @@ -1,267 +0,0 @@ -import argparse -import os - -import torch -import torch.nn as nn -from torch.utils.data import DataLoader -import torchvision -from torchvision.transforms import Compose, ToTensor, Resize -from torch import optim -import numpy as np -from torch.hub import tqdm - - -class PatchExtractor(nn.Module): - def __init__(self, patch_size=16): - super().__init__() - self.patch_size = patch_size - - def forward(self, input_data): - batch_size, channels, height, width = input_data.size() - assert height % self.patch_size == 0 and width % self.patch_size == 0, \ - f"Input height ({height}) and width ({width}) must be divisible by patch size ({self.patch_size})" - - num_patches_h = height // self.patch_size - num_patches_w = width // self.patch_size - num_patches = num_patches_h * num_patches_w - - patches = input_data.unfold(2, self.patch_size, self.patch_size). \ - unfold(3, self.patch_size, self.patch_size). \ - permute(0, 2, 3, 1, 4, 5). \ - contiguous(). \ - view(batch_size, num_patches, -1) - - # Expected shape of a patch on default settings is (4, 196, 768) - - return patches - - -class InputEmbedding(nn.Module): - - def __init__(self, args): - super(InputEmbedding, self).__init__() - self.patch_size = args.patch_size - self.n_channels = args.n_channels - self.latent_size = args.latent_size - use_cuda = not args.no_cuda and torch.cuda.is_available() - self.device = torch.device("cuda" if use_cuda else "cpu") - self.batch_size = args.batch_size - self.input_size = self.patch_size * self.patch_size * self.n_channels - - # Linear projection - self.LinearProjection = nn.Linear(self.input_size, self.latent_size) - # Class token - self.class_token = nn.Parameter(torch.randn(self.batch_size, 1, self.latent_size)).to(self.device) - # Positional embedding - self.pos_embedding = nn.Parameter(torch.randn(self.batch_size, 1, self.latent_size)).to(self.device) - - def forward(self, input_data): - input_data = input_data.to(self.device) - # Patchifying the Image - patchify = PatchExtractor(patch_size=self.patch_size) - patches = patchify(input_data) - - linear_projection = self.LinearProjection(patches).to(self.device) - b, n, _ = linear_projection.shape - linear_projection = torch.cat((self.class_token, linear_projection), dim=1) - pos_embed = self.pos_embedding[:, :n + 1, :] - linear_projection += pos_embed - - return linear_projection - - -class EncoderBlock(nn.Module): - - def __init__(self, args): - super(EncoderBlock, self).__init__() - - self.latent_size = args.latent_size - self.num_heads = args.num_heads - self.dropout = args.dropout - self.norm = nn.LayerNorm(self.latent_size) - self.attention = nn.MultiheadAttention(self.latent_size, self.num_heads, dropout=self.dropout) - self.enc_MLP = nn.Sequential( - nn.Linear(self.latent_size, self.latent_size * 4), - nn.GELU(), - nn.Dropout(self.dropout), - nn.Linear(self.latent_size * 4, self.latent_size), - nn.Dropout(self.dropout) - ) - - def forward(self, emb_patches): - first_norm = self.norm(emb_patches) - attention_out = self.attention(first_norm, first_norm, first_norm)[0] - first_added = attention_out + emb_patches - second_norm = self.norm(first_added) - mlp_out = self.enc_MLP(second_norm) - output = mlp_out + first_added - - return output - - -class ViT(nn.Module): - def __init__(self, args): - super(ViT, self).__init__() - - self.num_encoders = args.num_encoders - self.latent_size = args.latent_size - self.num_classes = args.num_classes - self.dropout = args.dropout - - self.embedding = InputEmbedding(args) - # Encoder Stack - self.encoders = nn.ModuleList([EncoderBlock(args) for _ in range(self.num_encoders)]) - self.MLPHead = nn.Sequential( - nn.LayerNorm(self.latent_size), - nn.Linear(self.latent_size, self.latent_size), - nn.Linear(self.latent_size, self.num_classes), - ) - - def forward(self, test_input): - enc_output = self.embedding(test_input) - for enc_layer in self.encoders: - enc_output = enc_layer(enc_output) - - class_token_embed = enc_output[:, 0] - return self.MLPHead(class_token_embed) - - -class TrainEval: - - def __init__(self, args, model, train_dataloader, val_dataloader, optimizer, criterion, device): - self.model = model - self.train_dataloader = train_dataloader - self.val_dataloader = val_dataloader - self.optimizer = optimizer - self.criterion = criterion - self.epoch = args.epochs - self.device = device - self.args = args - - def train_fn(self, current_epoch): - self.model.train() - total_loss = 0.0 - tk = tqdm(self.train_dataloader, desc="EPOCH" + "[TRAIN]" + str(current_epoch + 1) + "/" + str(self.epoch)) - - for t, data in enumerate(tk): - images, labels = data - images, labels = images.to(self.device), labels.to(self.device) - self.optimizer.zero_grad() - logits = self.model(images) - loss = self.criterion(logits, labels) - loss.backward() - self.optimizer.step() - - total_loss += loss.item() - tk.set_postfix({"Loss": "%6f" % float(total_loss / (t + 1))}) - if self.args.dry_run: - break - - return total_loss / len(self.train_dataloader) - - def eval_fn(self, current_epoch): - self.model.eval() - total_loss = 0.0 - tk = tqdm(self.val_dataloader, desc="EPOCH" + "[VALID]" + str(current_epoch + 1) + "/" + str(self.epoch)) - - for t, data in enumerate(tk): - images, labels = data - images, labels = images.to(self.device), labels.to(self.device) - - logits = self.model(images) - loss = self.criterion(logits, labels) - - total_loss += loss.item() - tk.set_postfix({"Loss": "%6f" % float(total_loss / (t + 1))}) - if self.args.dry_run: - break - - return total_loss / len(self.val_dataloader) - - def train(self): - best_valid_loss = np.inf - best_train_loss = np.inf - for i in range(self.epoch): - train_loss = self.train_fn(i) - val_loss = self.eval_fn(i) - - if val_loss < best_valid_loss: - torch.save(self.model.state_dict(), "best-weights.pt") - print("Saved Best Weights") - best_valid_loss = val_loss - best_train_loss = train_loss - print(f"Training Loss : {best_train_loss}") - print(f"Valid Loss : {best_valid_loss}") - - ''' - On default settings: - - Training Loss : 2.3081023390197752 - Valid Loss : 2.302861615943909 - - However, this score is not competitive compared to the - high results in the original paper, which were achieved - through pre-training on JFT-300M dataset, then fine-tuning - it on the target dataset. To improve the model quality - without pre-training, we could try training for more epochs, - using more Transformer layers, resizing images or changing - patch size, - ''' - - -def main(): - parser = argparse.ArgumentParser(description='Vision Transformer in PyTorch') - parser.add_argument('--no-cuda', action='store_true', default=False, - help='disables CUDA training') - parser.add_argument('--patch-size', type=int, default=16, - help='patch size for images (default : 16)') - parser.add_argument('--latent-size', type=int, default=768, - help='latent size (default : 768)') - parser.add_argument('--n-channels', type=int, default=3, - help='number of channels in images (default : 3 for RGB)') - parser.add_argument('--num-heads', type=int, default=12, - help='(default : 16)') - parser.add_argument('--num-encoders', type=int, default=12, - help='number of encoders (default : 12)') - parser.add_argument('--dropout', type=int, default=0.1, - help='dropout value (default : 0.1)') - parser.add_argument('--img-size', type=int, default=224, - help='image size to be reshaped to (default : 224') - parser.add_argument('--num-classes', type=int, default=10, - help='number of classes in dataset (default : 10 for CIFAR10)') - parser.add_argument('--epochs', type=int, default=10, - help='number of epochs (default : 10)') - parser.add_argument('--lr', type=float, default=1e-2, - help='base learning rate (default : 0.01)') - parser.add_argument('--weight-decay', type=int, default=3e-2, - help='weight decay value (default : 0.03)') - parser.add_argument('--batch-size', type=int, default=4, - help='batch size (default : 4)') - parser.add_argument('--dry-run', action='store_true', default=False, - help='quickly check a single pass') - args = parser.parse_args() - - use_cuda = not args.no_cuda and torch.cuda.is_available() - device = torch.device("cuda" if use_cuda else "cpu") - - transforms = Compose([ - Resize((args.img_size, args.img_size)), - ToTensor() - ]) - - dataset_path = os.getenv("FEDML_DATASET_PATH") - train_data = torchvision.datasets.CIFAR10(root=dataset_path, train=True, download=True, transform=transforms) - valid_data = torchvision.datasets.CIFAR10(root=dataset_path, train=False, download=True, transform=transforms) - train_loader = DataLoader(train_data, batch_size=args.batch_size, shuffle=True) - valid_loader = DataLoader(valid_data, batch_size=args.batch_size, shuffle=True) - - model = ViT(args).to(device) - - optimizer = optim.Adam(model.parameters(), lr=args.lr, weight_decay=args.weight_decay) - criterion = nn.CrossEntropyLoss() - - TrainEval(args, model, train_loader, valid_loader, optimizer, criterion, device).train() - - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/python/examples/launch/train_build_package/train_job.yaml b/python/examples/launch/train_build_package/train_job.yaml index 70e41e0fc7..770d177761 100755 --- a/python/examples/launch/train_build_package/train_job.yaml +++ b/python/examples/launch/train_build_package/train_job.yaml @@ -1,7 +1,7 @@ # Local directory where your source code resides. # It should be the relative path to this job yaml file or the absolute path. # If your job doesn't contain any source code, it can be empty. -workspace: . +workspace: "./src" # Running entry commands which will be executed as the job entry point. # If an error occurs, you should exit with a non-zero code, e.g. exit 1. @@ -14,14 +14,11 @@ job_type: train # options: train, deploy, federate # Bootstrap shell commands which will be executed before running entry commands. # Support multiple lines, which can be empty. -bootstrap: | - echo "Bootstrap finished." +bootstrap: bash bootstrap.sh computing: minimum_num_gpus: 1 # minimum # of GPUs to provision maximum_cost_per_hour: $3000 # max cost per hour for your job per gpu card - #allow_cross_cloud_resources: true # true, false - #device_type: CPU # options: GPU, CPU, hybrid resource_type: A100-80G # e.g., A100-80G, please check the resource type list by "fedml show-resource-type" or visiting URL: https://open.fedml.ai/accelerator_resource_type data_args: @@ -36,4 +33,4 @@ model_args: output_dim: '10' training_params: - learning_rate: 0.004 \ No newline at end of file + learning_rate: 0.004 diff --git a/python/fedml/api/modules/federate.py b/python/fedml/api/modules/federate.py index b889b5e0c8..1824593238 100644 --- a/python/fedml/api/modules/federate.py +++ b/python/fedml/api/modules/federate.py @@ -5,6 +5,7 @@ from fedml.computing.scheduler.comm_utils.sys_utils import generate_yaml_doc from fedml.computing.scheduler.comm_utils.yaml_utils import load_yaml_config from fedml.computing.scheduler.comm_utils.constants import SchedulerConstants +from fedml.computing.scheduler.scheduler_entry.constants import Constants as SchedulerEntryConstants import fedml.api.modules.build from fedml.computing.scheduler.scheduler_entry.launch_manager import FedMLLaunchManager @@ -66,8 +67,8 @@ def build_with_job_yaml(job_yaml_file, dest_folder=None): shutil.copyfile(server_package, dest_package) print(f"Your server package file is located at: {dest_package}") - bootstrap_bat_file = os.path.join(job_dir_path, "bootstrap.bat") - bootstrap_sh_file = os.path.join(job_dir_path, "bootstrap.sh") + bootstrap_sh_file = os.path.join(job_dir_path, SchedulerEntryConstants.BOOTSTRAP_FILE_NAME) + bootstrap_bat_file = bootstrap_sh_file.rstrip(".sh") + ".bat" job_entry_bat_file = os.path.join( job_dir_path, SchedulerConstants.LAUNCH_JOB_DEFAULT_ENTRY_NAME.rstrip('.sh') + '.bat') job_entry_sh_file = os.path.join(job_dir_path, SchedulerConstants.LAUNCH_JOB_DEFAULT_ENTRY_NAME) diff --git a/python/fedml/api/modules/train.py b/python/fedml/api/modules/train.py index 2c21a02a97..d0a4fe8bf9 100644 --- a/python/fedml/api/modules/train.py +++ b/python/fedml/api/modules/train.py @@ -5,14 +5,17 @@ from fedml.computing.scheduler.comm_utils.sys_utils import generate_yaml_doc from fedml.computing.scheduler.comm_utils.yaml_utils import load_yaml_config from fedml.computing.scheduler.comm_utils.constants import SchedulerConstants +from fedml.computing.scheduler.scheduler_entry.constants import Constants as SchedulerEntryConstants from fedml.computing.scheduler.scheduler_entry.launch_manager import FedMLLaunchManager import fedml.api.modules.build def build(source_folder, entry_point, entry_args, config_folder, dest_folder, ignore, model_name, model_cache_path, input_dim, output_dim, dataset_name, dataset_type, dataset_path): + # Check the config file config_file_path = os.path.join(config_folder, ModuleConstants.FEDML_CONFIG_YAML_FILE) + if not os.path.exists(config_file_path): print(f"Please make sure the following config file exists. \n{config_file_path}") return @@ -37,8 +40,10 @@ def build(source_folder, entry_point, entry_args, config_folder, dest_folder, ig def build_with_job_yaml(job_yaml_file, dest_folder=None): + job_config, app_config, client_package, server_package = FedMLLaunchManager.get_instance().prepare_launch( job_yaml_file) + if client_package is None or os.path.exists(client_package) is False: print("Build failed, please check your job yaml file.") return @@ -52,11 +57,11 @@ def build_with_job_yaml(job_yaml_file, dest_folder=None): os.path.join(dest_folder, os.path.basename(client_package))) shutil.copyfile(client_package, dest_package) - bootstrap_bat_file = os.path.join(job_dir_path, "bootstrap.bat") - bootstrap_sh_file = os.path.join(job_dir_path, "bootstrap.sh") - job_entry_bat_file = os.path.join( - job_dir_path, SchedulerConstants.LAUNCH_JOB_DEFAULT_ENTRY_NAME.rstrip('.sh') + '.bat') + bootstrap_sh_file = os.path.join(job_dir_path, SchedulerEntryConstants.BOOTSTRAP_FILE_NAME) + bootstrap_bat_file = bootstrap_sh_file.rstrip(".sh") + ".bat" job_entry_sh_file = os.path.join(job_dir_path, SchedulerConstants.LAUNCH_JOB_DEFAULT_ENTRY_NAME) + job_entry_bat_file = job_entry_sh_file.rstrip(".sh") + '.bat' + if os.path.exists(bootstrap_bat_file): os.remove(bootstrap_bat_file) if os.path.exists(bootstrap_sh_file): diff --git a/python/fedml/computing/scheduler/comm_utils/sys_utils.py b/python/fedml/computing/scheduler/comm_utils/sys_utils.py index f5d6ea5462..64313b0864 100644 --- a/python/fedml/computing/scheduler/comm_utils/sys_utils.py +++ b/python/fedml/computing/scheduler/comm_utils/sys_utils.py @@ -597,6 +597,38 @@ def remove_simulator_process(data_dir, runner_info_dir, process_id): pass +def remove_files(file_paths: List[str]): + """ + Remove files if they exist. + + Args: + file_paths: List of file paths + + Usage: + file_list = ["file4.txt", "file5.txt", "file6.txt"] + remove_files(file_list) + """ + if not isinstance(file_paths, list): + raise ValueError("file_paths must be a list of file paths.") + + for path in file_paths: + if os.path.exists(path): + os.remove(path) + + +def convert_and_remove_bat_files(shell_script_paths: List[str]): + if not isinstance(shell_script_paths, list): + raise ValueError("sh_file_paths must be a list of file paths.") + + # Convert to bat file paths + bat_file_paths = list(map(lambda path: path[:-2] + 'bat', shell_script_paths)) + + # Filter out non-bat paths + bat_file_paths = list(filter(lambda path: path.endswith('.bat'), bat_file_paths)) + + remove_files(bat_file_paths) + + def simulator_process_is_running(process_id): for process in psutil.process_iter(): if str(process.pid) == str(process_id): diff --git a/python/fedml/computing/scheduler/scheduler_entry/constants.py b/python/fedml/computing/scheduler/scheduler_entry/constants.py index 3108218dec..e83701460c 100755 --- a/python/fedml/computing/scheduler/scheduler_entry/constants.py +++ b/python/fedml/computing/scheduler/scheduler_entry/constants.py @@ -33,7 +33,7 @@ class Constants(Singleton): FEDML_LAUNCH_JOB_TEMP_DIR = "tmp" - BOOTSTRAP_FILE_NAME = "bootstrap.sh" + BOOTSTRAP_FILE_NAME = "fedml_bootstrap_generated.sh" STD_CONFIG_ENV_SECTION = "environment_args" STD_CONFIG_ENV_SECTION_BOOTSTRAP_KEY = "bootstrap" diff --git a/python/fedml/computing/scheduler/scheduler_entry/launch_manager.py b/python/fedml/computing/scheduler/scheduler_entry/launch_manager.py index 89960fa62c..93a86b95c1 100755 --- a/python/fedml/computing/scheduler/scheduler_entry/launch_manager.py +++ b/python/fedml/computing/scheduler/scheduler_entry/launch_manager.py @@ -533,28 +533,28 @@ def cleanup_temp_files(self): Constants.LAUNCH_JOB_LAUNCH_CONF_FOLDER_NAME) shutil.rmtree(conf_folder, ignore_errors=True) + files_to_remove = [] source_full_path = os.path.join(self.executable_file_folder, self.executable_file) if os.path.exists(source_full_path): - os.remove(source_full_path) boostrap_path = os.path.join(self.executable_file_folder, Constants.BOOTSTRAP_FILE_NAME) - if os.path.exists(boostrap_path): - os.remove(boostrap_path) + files_to_remove.extend([source_full_path, boostrap_path]) server_source_full_path = os.path.join(self.executable_file_folder, self.server_executable_file) - if os.path.exists(server_source_full_path): - os.remove(server_source_full_path) + files_to_remove.append(server_source_full_path) source_full_path_to_base = os.path.join(self.base_dir, self.executable_file_folder, self.executable_file) if os.path.exists(source_full_path_to_base): - os.remove(source_full_path_to_base) boostrap_path = os.path.join(self.base_dir, self.executable_file_folder, Constants.BOOTSTRAP_FILE_NAME) - if os.path.exists(boostrap_path): - os.remove(boostrap_path) + files_to_remove.extend([source_full_path_to_base, boostrap_path]) server_source_full_path_to_base = os.path.join(self.base_dir, self.executable_file_folder, self.server_executable_file) if os.path.exists(server_source_full_path_to_base): - os.remove(server_source_full_path_to_base) + files_to_remove.append(server_source_full_path_to_base) + + sys_utils.remove_files(files_to_remove) + sys_utils.convert_and_remove_bat_files(files_to_remove) + def read_gitignore_file(self): try: From ec64ed3f3b12859f5c5302ed063e2eba0f0c7ab5 Mon Sep 17 00:00:00 2001 From: Alay Shah Date: Sat, 9 Mar 2024 15:17:56 -0800 Subject: [PATCH 064/135] Update example --- .../train_build_package/src/bootstrap.sh | 10 + .../launch/train_build_package/src/train.py | 267 ++++++++++++++++++ 2 files changed, 277 insertions(+) create mode 100644 python/examples/launch/train_build_package/src/bootstrap.sh create mode 100644 python/examples/launch/train_build_package/src/train.py diff --git a/python/examples/launch/train_build_package/src/bootstrap.sh b/python/examples/launch/train_build_package/src/bootstrap.sh new file mode 100644 index 0000000000..25a2b1096a --- /dev/null +++ b/python/examples/launch/train_build_package/src/bootstrap.sh @@ -0,0 +1,10 @@ +### don't modify this part ### +set -x +############################## + +pip install -r requirements.txt +echo "Bootstrap finished." + +### don't modify this part ### +exit 0 +############################## diff --git a/python/examples/launch/train_build_package/src/train.py b/python/examples/launch/train_build_package/src/train.py new file mode 100644 index 0000000000..11f6d8edc6 --- /dev/null +++ b/python/examples/launch/train_build_package/src/train.py @@ -0,0 +1,267 @@ +import argparse +import os + +import torch +import torch.nn as nn +from torch.utils.data import DataLoader +import torchvision +from torchvision.transforms import Compose, ToTensor, Resize +from torch import optim +import numpy as np +from torch.hub import tqdm + + +class PatchExtractor(nn.Module): + def __init__(self, patch_size=16): + super().__init__() + self.patch_size = patch_size + + def forward(self, input_data): + batch_size, channels, height, width = input_data.size() + assert height % self.patch_size == 0 and width % self.patch_size == 0, \ + f"Input height ({height}) and width ({width}) must be divisible by patch size ({self.patch_size})" + + num_patches_h = height // self.patch_size + num_patches_w = width // self.patch_size + num_patches = num_patches_h * num_patches_w + + patches = input_data.unfold(2, self.patch_size, self.patch_size). \ + unfold(3, self.patch_size, self.patch_size). \ + permute(0, 2, 3, 1, 4, 5). \ + contiguous(). \ + view(batch_size, num_patches, -1) + + # Expected shape of a patch on default settings is (4, 196, 768) + + return patches + + +class InputEmbedding(nn.Module): + + def __init__(self, args): + super(InputEmbedding, self).__init__() + self.patch_size = args.patch_size + self.n_channels = args.n_channels + self.latent_size = args.latent_size + use_cuda = not args.no_cuda and torch.cuda.is_available() + self.device = torch.device("cuda" if use_cuda else "cpu") + self.batch_size = args.batch_size + self.input_size = self.patch_size * self.patch_size * self.n_channels + + # Linear projection + self.LinearProjection = nn.Linear(self.input_size, self.latent_size) + # Class token + self.class_token = nn.Parameter(torch.randn(self.batch_size, 1, self.latent_size)).to(self.device) + # Positional embedding + self.pos_embedding = nn.Parameter(torch.randn(self.batch_size, 1, self.latent_size)).to(self.device) + + def forward(self, input_data): + input_data = input_data.to(self.device) + # Patchifying the Image + patchify = PatchExtractor(patch_size=self.patch_size) + patches = patchify(input_data) + + linear_projection = self.LinearProjection(patches).to(self.device) + b, n, _ = linear_projection.shape + linear_projection = torch.cat((self.class_token, linear_projection), dim=1) + pos_embed = self.pos_embedding[:, :n + 1, :] + linear_projection += pos_embed + + return linear_projection + + +class EncoderBlock(nn.Module): + + def __init__(self, args): + super(EncoderBlock, self).__init__() + + self.latent_size = args.latent_size + self.num_heads = args.num_heads + self.dropout = args.dropout + self.norm = nn.LayerNorm(self.latent_size) + self.attention = nn.MultiheadAttention(self.latent_size, self.num_heads, dropout=self.dropout) + self.enc_MLP = nn.Sequential( + nn.Linear(self.latent_size, self.latent_size * 4), + nn.GELU(), + nn.Dropout(self.dropout), + nn.Linear(self.latent_size * 4, self.latent_size), + nn.Dropout(self.dropout) + ) + + def forward(self, emb_patches): + first_norm = self.norm(emb_patches) + attention_out = self.attention(first_norm, first_norm, first_norm)[0] + first_added = attention_out + emb_patches + second_norm = self.norm(first_added) + mlp_out = self.enc_MLP(second_norm) + output = mlp_out + first_added + + return output + + +class ViT(nn.Module): + def __init__(self, args): + super(ViT, self).__init__() + + self.num_encoders = args.num_encoders + self.latent_size = args.latent_size + self.num_classes = args.num_classes + self.dropout = args.dropout + + self.embedding = InputEmbedding(args) + # Encoder Stack + self.encoders = nn.ModuleList([EncoderBlock(args) for _ in range(self.num_encoders)]) + self.MLPHead = nn.Sequential( + nn.LayerNorm(self.latent_size), + nn.Linear(self.latent_size, self.latent_size), + nn.Linear(self.latent_size, self.num_classes), + ) + + def forward(self, test_input): + enc_output = self.embedding(test_input) + for enc_layer in self.encoders: + enc_output = enc_layer(enc_output) + + class_token_embed = enc_output[:, 0] + return self.MLPHead(class_token_embed) + + +class TrainEval: + + def __init__(self, args, model, train_dataloader, val_dataloader, optimizer, criterion, device): + self.model = model + self.train_dataloader = train_dataloader + self.val_dataloader = val_dataloader + self.optimizer = optimizer + self.criterion = criterion + self.epoch = args.epochs + self.device = device + self.args = args + + def train_fn(self, current_epoch): + self.model.train() + total_loss = 0.0 + tk = tqdm(self.train_dataloader, desc="EPOCH" + "[TRAIN]" + str(current_epoch + 1) + "/" + str(self.epoch)) + + for t, data in enumerate(tk): + images, labels = data + images, labels = images.to(self.device), labels.to(self.device) + self.optimizer.zero_grad() + logits = self.model(images) + loss = self.criterion(logits, labels) + loss.backward() + self.optimizer.step() + + total_loss += loss.item() + tk.set_postfix({"Loss": "%6f" % float(total_loss / (t + 1))}) + if self.args.dry_run: + break + + return total_loss / len(self.train_dataloader) + + def eval_fn(self, current_epoch): + self.model.eval() + total_loss = 0.0 + tk = tqdm(self.val_dataloader, desc="EPOCH" + "[VALID]" + str(current_epoch + 1) + "/" + str(self.epoch)) + + for t, data in enumerate(tk): + images, labels = data + images, labels = images.to(self.device), labels.to(self.device) + + logits = self.model(images) + loss = self.criterion(logits, labels) + + total_loss += loss.item() + tk.set_postfix({"Loss": "%6f" % float(total_loss / (t + 1))}) + if self.args.dry_run: + break + + return total_loss / len(self.val_dataloader) + + def train(self): + best_valid_loss = np.inf + best_train_loss = np.inf + for i in range(self.epoch): + train_loss = self.train_fn(i) + val_loss = self.eval_fn(i) + + if val_loss < best_valid_loss: + torch.save(self.model.state_dict(), "best-weights.pt") + print("Saved Best Weights") + best_valid_loss = val_loss + best_train_loss = train_loss + print(f"Training Loss : {best_train_loss}") + print(f"Valid Loss : {best_valid_loss}") + + ''' + On default settings: + + Training Loss : 2.3081023390197752 + Valid Loss : 2.302861615943909 + + However, this score is not competitive compared to the + high results in the original paper, which were achieved + through pre-training on JFT-300M dataset, then fine-tuning + it on the target dataset. To improve the model quality + without pre-training, we could try training for more epochs, + using more Transformer layers, resizing images or changing + patch size, + ''' + + +def main(): + parser = argparse.ArgumentParser(description='Vision Transformer in PyTorch') + parser.add_argument('--no-cuda', action='store_true', default=False, + help='disables CUDA training') + parser.add_argument('--patch-size', type=int, default=16, + help='patch size for images (default : 16)') + parser.add_argument('--latent-size', type=int, default=768, + help='latent size (default : 768)') + parser.add_argument('--n-channels', type=int, default=3, + help='number of channels in images (default : 3 for RGB)') + parser.add_argument('--num-heads', type=int, default=12, + help='(default : 16)') + parser.add_argument('--num-encoders', type=int, default=12, + help='number of encoders (default : 12)') + parser.add_argument('--dropout', type=int, default=0.1, + help='dropout value (default : 0.1)') + parser.add_argument('--img-size', type=int, default=224, + help='image size to be reshaped to (default : 224') + parser.add_argument('--num-classes', type=int, default=10, + help='number of classes in dataset (default : 10 for CIFAR10)') + parser.add_argument('--epochs', type=int, default=10, + help='number of epochs (default : 10)') + parser.add_argument('--lr', type=float, default=1e-2, + help='base learning rate (default : 0.01)') + parser.add_argument('--weight-decay', type=int, default=3e-2, + help='weight decay value (default : 0.03)') + parser.add_argument('--batch-size', type=int, default=4, + help='batch size (default : 4)') + parser.add_argument('--dry-run', action='store_true', default=False, + help='quickly check a single pass') + args = parser.parse_args() + + use_cuda = not args.no_cuda and torch.cuda.is_available() + device = torch.device("cuda" if use_cuda else "cpu") + + transforms = Compose([ + Resize((args.img_size, args.img_size)), + ToTensor() + ]) + + dataset_path = os.getenv("FEDML_DATASET_PATH") + train_data = torchvision.datasets.CIFAR10(root=dataset_path, train=True, download=True, transform=transforms) + valid_data = torchvision.datasets.CIFAR10(root=dataset_path, train=False, download=True, transform=transforms) + train_loader = DataLoader(train_data, batch_size=args.batch_size, shuffle=True) + valid_loader = DataLoader(valid_data, batch_size=args.batch_size, shuffle=True) + + model = ViT(args).to(device) + + optimizer = optim.Adam(model.parameters(), lr=args.lr, weight_decay=args.weight_decay) + criterion = nn.CrossEntropyLoss() + + TrainEval(args, model, train_loader, valid_loader, optimizer, criterion, device).train() + + +if __name__ == "__main__": + main() \ No newline at end of file From 43b01e5a7a43dcaa9e23dfa6d013c32daef6c527 Mon Sep 17 00:00:00 2001 From: Alay Shah Date: Sat, 9 Mar 2024 16:46:33 -0800 Subject: [PATCH 065/135] Fix generating environment variables from job configurations to support multi-level nesting --- python/fedml/computing/scheduler/comm_utils/job_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/fedml/computing/scheduler/comm_utils/job_utils.py b/python/fedml/computing/scheduler/comm_utils/job_utils.py index d8dd8e00b7..68fed1c8bb 100644 --- a/python/fedml/computing/scheduler/comm_utils/job_utils.py +++ b/python/fedml/computing/scheduler/comm_utils/job_utils.py @@ -585,14 +585,14 @@ def get_env_from_dict( return {} for config_key, config_value in config_dict.items(): + config_key = f"{config_key_path}_{config_key}".upper() if config_key_path else str(config_key).upper() if isinstance(config_value, dict): JobRunnerUtils.get_env_from_dict( export_cmd, config_value, export_env_command_list=export_env_command_list, env_name_value_map=env_name_value_map, config_key_path=config_key ) else: - env_name = f"FEDML_ENV_{'' if config_key_path == '' else str(config_key_path).upper() + '_'}" \ - f"{str(config_key).upper()}" + env_name = f"FEDML_ENV_{config_key}" config_value = str(config_value).replace("\n", ";") config_value = str(config_value).replace("\"", "\\\"") export_env_command_list.append(f"{export_cmd} {env_name}=\"{config_value}\"\n") From 0543d43ef532cb48d5d6d2ed06f9db4218d5fa6f Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 13 Mar 2024 17:43:50 +0800 Subject: [PATCH 066/135] [CoreEngine] subscribe topics for reporting device info to mlops. --- python/fedml/__init__.py | 2 +- python/fedml/computing/scheduler/slave/client_runner.py | 8 ++++++++ python/setup.py | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index aef492b5f4..e3f14e1fb5 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.27.dev6" +__version__ = "0.8.28.dev2" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release diff --git a/python/fedml/computing/scheduler/slave/client_runner.py b/python/fedml/computing/scheduler/slave/client_runner.py index e06416168c..888e117f47 100755 --- a/python/fedml/computing/scheduler/slave/client_runner.py +++ b/python/fedml/computing/scheduler/slave/client_runner.py @@ -1586,6 +1586,7 @@ def on_agent_mqtt_connected(self, mqtt_client_object): mqtt_client_object.subscribe(topic_report_status, qos=2) mqtt_client_object.subscribe(topic_ota_msg, qos=2) mqtt_client_object.subscribe(topic_request_device_info, qos=2) + mqtt_client_object.subscribe(topic_request_device_info_from_mlops, qos=2) mqtt_client_object.subscribe(topic_client_logout, qos=2) self.subscribed_topics.clear() @@ -1595,6 +1596,7 @@ def on_agent_mqtt_connected(self, mqtt_client_object): self.subscribed_topics.append(topic_report_status) self.subscribed_topics.append(topic_ota_msg) self.subscribed_topics.append(topic_request_device_info) + self.subscribed_topics.append(topic_request_device_info_from_mlops) self.subscribed_topics.append(topic_client_logout) # Subscribe the messages for federated learning. @@ -1651,16 +1653,22 @@ def subscribe_fl_msgs(self): self.add_message_listener(topic_request_device_info, self.callback_report_device_info) self.mqtt_mgr.add_message_listener(topic_request_device_info, self.listener_message_dispatch_center) + topic_request_device_info_from_mlops = f"deploy/mlops/client_agent/request_device_info/{self.general_edge_id}" + self.add_message_listener(topic_request_device_info_from_mlops, self.response_device_info_to_mlops) + self.mqtt_mgr.add_message_listener(topic_request_device_info_from_mlops, self.listener_message_dispatch_center) + # Subscribe topics for starting train, stopping train and fetching client status. self.mqtt_mgr.subscribe_msg(topic_start_train) self.mqtt_mgr.subscribe_msg(topic_stop_train) self.mqtt_mgr.subscribe_msg(topic_client_status) self.mqtt_mgr.subscribe_msg(topic_request_device_info) + self.mqtt_mgr.subscribe_msg(topic_request_device_info_from_mlops) self.subscribed_topics.append(topic_start_train) self.subscribed_topics.append(topic_stop_train) self.subscribed_topics.append(topic_client_status) self.subscribed_topics.append(topic_request_device_info) + self.subscribed_topics.append(topic_request_device_info_from_mlops) def on_agent_mqtt_disconnected(self, mqtt_client_object): MLOpsStatus.get_instance().set_client_agent_status( diff --git a/python/setup.py b/python/setup.py index e2790e3460..194556f365 100644 --- a/python/setup.py +++ b/python/setup.py @@ -116,7 +116,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.27.dev6", + version="0.8.28.dev2", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 53990e27b8c3f976d88b7ce4520f0041c7299bd2 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 13 Mar 2024 18:01:01 +0800 Subject: [PATCH 067/135] [CoreEngine] update the subscribed topics for reporting device info to mlops. --- python/fedml/__init__.py | 2 +- python/fedml/computing/scheduler/slave/client_runner.py | 2 +- python/setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index e3f14e1fb5..091acf258b 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.28.dev2" +__version__ = "0.8.28.dev3" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release diff --git a/python/fedml/computing/scheduler/slave/client_runner.py b/python/fedml/computing/scheduler/slave/client_runner.py index 888e117f47..f99d9015f6 100755 --- a/python/fedml/computing/scheduler/slave/client_runner.py +++ b/python/fedml/computing/scheduler/slave/client_runner.py @@ -1570,7 +1570,7 @@ def on_agent_mqtt_connected(self, mqtt_client_object): self.add_message_listener(topic_request_device_info, self.callback_report_device_info) self.mqtt_mgr.add_message_listener(topic_request_device_info, self.listener_message_dispatch_center) - topic_request_device_info_from_mlops = f"deploy/mlops/client_agent/request_device_info/{self.edge_id}" + topic_request_device_info_from_mlops = f"deploy/mlops/slave_agent/request_device_info/{self.edge_id}" self.add_message_listener(topic_request_device_info_from_mlops, self.response_device_info_to_mlops) self.mqtt_mgr.add_message_listener(topic_request_device_info_from_mlops, self.listener_message_dispatch_center) diff --git a/python/setup.py b/python/setup.py index 194556f365..fafcd9b75b 100644 --- a/python/setup.py +++ b/python/setup.py @@ -116,7 +116,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.28.dev2", + version="0.8.28.dev3", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From ba686342ed41be017279ba5e057328e5b1a5449f Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 13 Mar 2024 18:56:14 +0800 Subject: [PATCH 068/135] [CoreEngine] update the subscribed topics for reporting device info to mlops. --- python/fedml/__init__.py | 2 +- .../scheduler/slave/client_runner.py | 30 +++++++++++++++---- python/setup.py | 2 +- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 091acf258b..7eaf209121 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.28.dev3" +__version__ = "0.8.28.dev4" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release diff --git a/python/fedml/computing/scheduler/slave/client_runner.py b/python/fedml/computing/scheduler/slave/client_runner.py index f99d9015f6..88122f4109 100755 --- a/python/fedml/computing/scheduler/slave/client_runner.py +++ b/python/fedml/computing/scheduler/slave/client_runner.py @@ -1570,9 +1570,21 @@ def on_agent_mqtt_connected(self, mqtt_client_object): self.add_message_listener(topic_request_device_info, self.callback_report_device_info) self.mqtt_mgr.add_message_listener(topic_request_device_info, self.listener_message_dispatch_center) - topic_request_device_info_from_mlops = f"deploy/mlops/slave_agent/request_device_info/{self.edge_id}" - self.add_message_listener(topic_request_device_info_from_mlops, self.response_device_info_to_mlops) - self.mqtt_mgr.add_message_listener(topic_request_device_info_from_mlops, self.listener_message_dispatch_center) + topic_request_edge_device_info_from_mlops = f"deploy/mlops/slave_agent/request_device_info/{self.edge_id}" + self.add_message_listener(topic_request_edge_device_info_from_mlops, self.response_device_info_to_mlops) + self.mqtt_mgr.add_message_listener(topic_request_edge_device_info_from_mlops, self.listener_message_dispatch_center) + + topic_request_deploy_master_device_info_from_mlops = None + if self.model_device_server_id is not None: + topic_request_deploy_master_device_info_from_mlops = f"deploy/mlops/master_agent/request_device_info/{self.model_device_server_id}" + self.add_message_listener(topic_request_deploy_master_device_info_from_mlops, self.response_device_info_to_mlops) + self.mqtt_mgr.add_message_listener(topic_request_deploy_master_device_info_from_mlops, self.listener_message_dispatch_center) + + topic_request_deploy_slave_device_info_from_mlops = None + if self.model_device_client_edge_id_list is not None and len(self.model_device_client_edge_id_list) > 0: + topic_request_deploy_slave_device_info_from_mlops = f"deploy/mlops/slave_agent/request_device_info/{self.model_device_client_edge_id_list[0]}" + self.add_message_listener(topic_request_deploy_slave_device_info_from_mlops, self.response_device_info_to_mlops) + self.mqtt_mgr.add_message_listener(topic_request_deploy_slave_device_info_from_mlops, self.listener_message_dispatch_center) # Setup MQTT message listener to logout from MLOps. topic_client_logout = "mlops/client/logout/" + str(self.edge_id) @@ -1586,7 +1598,11 @@ def on_agent_mqtt_connected(self, mqtt_client_object): mqtt_client_object.subscribe(topic_report_status, qos=2) mqtt_client_object.subscribe(topic_ota_msg, qos=2) mqtt_client_object.subscribe(topic_request_device_info, qos=2) - mqtt_client_object.subscribe(topic_request_device_info_from_mlops, qos=2) + mqtt_client_object.subscribe(topic_request_edge_device_info_from_mlops, qos=2) + if topic_request_deploy_master_device_info_from_mlops is not None: + mqtt_client_object.subscribe(topic_request_deploy_master_device_info_from_mlops, qos=2) + if topic_request_deploy_slave_device_info_from_mlops is not None: + mqtt_client_object.subscribe(topic_request_deploy_slave_device_info_from_mlops, qos=2) mqtt_client_object.subscribe(topic_client_logout, qos=2) self.subscribed_topics.clear() @@ -1596,7 +1612,11 @@ def on_agent_mqtt_connected(self, mqtt_client_object): self.subscribed_topics.append(topic_report_status) self.subscribed_topics.append(topic_ota_msg) self.subscribed_topics.append(topic_request_device_info) - self.subscribed_topics.append(topic_request_device_info_from_mlops) + self.subscribed_topics.append(topic_request_edge_device_info_from_mlops) + if topic_request_deploy_master_device_info_from_mlops is not None: + self.subscribed_topics.append(topic_request_deploy_master_device_info_from_mlops) + if topic_request_deploy_slave_device_info_from_mlops is not None: + self.subscribed_topics.append(topic_request_deploy_slave_device_info_from_mlops) self.subscribed_topics.append(topic_client_logout) # Subscribe the messages for federated learning. diff --git a/python/setup.py b/python/setup.py index fafcd9b75b..e40207b966 100644 --- a/python/setup.py +++ b/python/setup.py @@ -116,7 +116,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.28.dev3", + version="0.8.28.dev4", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From 728d07acb1432d0ddbb4da174747b9e6221748ca Mon Sep 17 00:00:00 2001 From: Raphael Jin Date: Sun, 10 Mar 2024 23:04:33 -0400 Subject: [PATCH 069/135] [Deploy] Refactor Deploy with Replica Logic --- python/examples/deploy/dummy_job/config.yaml | 4 +- .../deploy/dummy_job/config/bootstrap.sh | 12 - .../scheduler/comm_utils/job_monitor.py | 149 ++-- .../scheduler/comm_utils/job_utils.py | 47 ++ .../scheduler/comm_utils/security_utils.py | 4 + .../device_client_constants.py | 1 + .../model_scheduler/device_client_runner.py | 329 +++++--- .../model_scheduler/device_model_cache.py | 189 +++-- .../model_scheduler/device_model_db.py | 62 +- .../device_model_deployment.py | 763 +++++++----------- .../model_scheduler/device_model_inference.py | 65 +- .../device_model_msg_object.py | 64 +- .../device_replica_controller.py | 414 ++++++++++ .../model_scheduler/device_replica_handler.py | 138 ++++ .../model_scheduler/device_server_runner.py | 524 +++++------- .../endpoint_monitor_protocol.py | 1 + .../scheduler_core/endpoint_sync_protocol.py | 78 +- python/fedml/core/mlops/mlops_runtime_log.py | 2 +- .../core/mlops/mlops_runtime_log_daemon.py | 2 + 19 files changed, 1679 insertions(+), 1169 deletions(-) delete mode 100644 python/examples/deploy/dummy_job/config/bootstrap.sh create mode 100644 python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py create mode 100644 python/fedml/computing/scheduler/model_scheduler/device_replica_handler.py diff --git a/python/examples/deploy/dummy_job/config.yaml b/python/examples/deploy/dummy_job/config.yaml index 80cee28230..5802c606d0 100644 --- a/python/examples/deploy/dummy_job/config.yaml +++ b/python/examples/deploy/dummy_job/config.yaml @@ -2,5 +2,5 @@ workspace: "./src" entry_point: "serve_main.py" bootstrap: | echo "Bootstrap start..." - sleep 15 - echo "Bootstrap finished" \ No newline at end of file + sleep 5 + echo "Bootstrap finished" diff --git a/python/examples/deploy/dummy_job/config/bootstrap.sh b/python/examples/deploy/dummy_job/config/bootstrap.sh deleted file mode 100644 index 79e9bf8071..0000000000 --- a/python/examples/deploy/dummy_job/config/bootstrap.sh +++ /dev/null @@ -1,12 +0,0 @@ -### don't modify this part ### -set -x -############################## - - -### please customize your script in this region #### -echo "Hello World1" -echo "Hello World2" - -### don't modify this part ### -exit 0 -############################## \ No newline at end of file diff --git a/python/fedml/computing/scheduler/comm_utils/job_monitor.py b/python/fedml/computing/scheduler/comm_utils/job_monitor.py index 3fdd856ca9..f97e92cf7f 100644 --- a/python/fedml/computing/scheduler/comm_utils/job_monitor.py +++ b/python/fedml/computing/scheduler/comm_utils/job_monitor.py @@ -256,7 +256,8 @@ def monitor_slave_endpoint_status(self): # Release the gpu ids print( - f"[endpoint/device][{job.job_id}/{job.edge_id}] Release gpu resource when woker endpoint failed on monitoring periodically.") + f"[endpoint/device][{job.job_id}/{job.edge_id}] Release gpu resource when worker " + f"endpoint failed on monitoring periodically.") JobRunnerUtils.get_instance().release_gpu_ids(job.job_id, job.edge_id) elif job.status == device_client_constants.ClientConstants.MSG_MLOPS_CLIENT_STATUS_FINISHED: @@ -269,75 +270,86 @@ def monitor_slave_endpoint_status(self): device_ids = endpoint_json.get("device_ids", []) logging.info(f"Check endpoint status for {job.job_id}:{job.edge_id}.") - if model_name is not None: - # Get model deployment result - deployment_result = FedMLModelDatabase.get_instance().get_deployment_result_with_device_id( - job.job_id, endpoint_name, model_name, job.edge_id) - if deployment_result is None: - continue + if model_name is None: + continue + + # Get replicas deployment result inside this device + deployment_result_list = FedMLModelDatabase.get_instance().get_deployment_result_with_device_id( + job.job_id, endpoint_name, model_name, job.edge_id) - status_result = FedMLModelDatabase.get_instance().get_deployment_status_with_device_id( - job.job_id, endpoint_name, model_name, job.edge_id) + if deployment_result_list is None: + continue - # Check the endpoint status - # TODO: Parallel this check + # Check the container (replica) ready probe + # TODO: Parallel this check + rank = -1 + for deployment_result in deployment_result_list: + rank += 1 is_endpoint_ready = self._check_and_reset_endpoint_status( job.job_id, job.edge_id, deployment_result, only_check_inference_ready_status=True) - # Get endpoint container name prefix - endpoint_container_name_prefix = device_client_constants.ClientConstants.get_endpoint_container_name( - endpoint_name, model_name, model_version, job.job_id, model_id, edge_id=job.edge_id) + # Get endpoint container name prefix, prepare for restart + endpoint_container_name_prefix = \ + (device_client_constants.ClientConstants.get_endpoint_container_name( + endpoint_name, model_name, model_version, job.job_id, model_id, + edge_id=job.edge_id)) - # Could be multiple containers for the same endpoint - num_containers = ContainerUtils.get_instance().get_container_rank_same_model( - endpoint_container_name_prefix) + endpoint_container_name = endpoint_container_name_prefix + f"__{rank}" + inference_port = -1 - for i in range(num_containers): - endpoint_container_name = endpoint_container_name_prefix + f"__{i}" - if not is_endpoint_ready: - # send unavailable status to the master agent - endpoint_sync_protocol.send_sync_inference_info( - device_ids[0], job.edge_id, job.job_id, endpoint_name, model_name, - model_id, model_version, inference_port=None, - disable=True) - - # [Critical] - # 1. After restart, - # the "running" status of container does NOT mean the endpoint is ready. - # 2. if local db has status updating, do not restart again - result_json = deployment_result - status = result_json.get("model_status", None) - - if status != device_server_constants.ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_UPDATING: - started, inference_port = ContainerUtils.get_instance().restart_container( - endpoint_container_name) - deployment_result[ - "model_status"] = device_server_constants.ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_UPDATING - - # Change the local port for next ready check - endpoint_sync_protocol.set_local_deployment_status_result( - job.job_id, endpoint_name, model_name, model_version, job.edge_id, - inference_port, status_result, deployment_result) - else: - started, inference_port = ContainerUtils.get_instance().start_container( + if is_endpoint_ready: + # Though it is ready, we still need to get the port + started, inference_port = ContainerUtils.get_instance().start_container( + endpoint_container_name) + else: + # Restart the container if the endpoint is not ready + # send unavailable status to the master agent + # TODO: Check the callback from the master agent + endpoint_sync_protocol.send_sync_inference_info( + device_ids[0], job.edge_id, job.job_id, endpoint_name, model_name, + model_id, model_version, inference_port=None, + disable=True, replica_no=rank+1) + + # [Critical] + # 1. After restart, the "running" status of container does NOT mean the endpoint is + # ready. Could be the container is still starting, or the endpoint is not ready. + # 2. if local db has status updating, do not restart again + result_json = deployment_result + status = result_json.get("model_status", None) + + if (status != device_server_constants.ServerConstants. + MSG_MODELOPS_DEPLOYMENT_STATUS_UPDATING): + # First time restart + started, inference_port = ContainerUtils.get_instance().restart_container( endpoint_container_name) + # Change the local port for next ready check, avoid restart again + deployment_result["model_status"] = (device_server_constants.ServerConstants. + MSG_MODELOPS_DEPLOYMENT_STATUS_UPDATING) + endpoint_sync_protocol.set_local_deployment_status_result( + job.job_id, endpoint_name, model_name, model_version, job.edge_id, + inference_port, None, deployment_result, replica_no=rank+1) + + # Report the status to the master agent if is_endpoint_ready: + assert inference_port != -1 deployment_result[ - "model_status"] = device_server_constants.ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED + "model_status"] = (device_server_constants.ServerConstants. + MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED) # Send the inference info to the master agent # TODO: Consistency control endpoint_sync_protocol.send_sync_inference_info( device_ids[0], job.edge_id, job.job_id, endpoint_name, model_name, - model_id, model_version, inference_port) + model_id, model_version, inference_port, replica_no=rank+1) # Change the local port for next ready check endpoint_sync_protocol.set_local_deployment_status_result( job.job_id, endpoint_name, model_name, model_version, job.edge_id, - inference_port, status_result, deployment_result) + inference_port, None, deployment_result, replica_no=rank+1) elif job.status == device_client_constants.ClientConstants.MSG_MLOPS_CLIENT_STATUS_OFFLINE: + # TODO: Bring the offline status online endpoint_json = json.loads(job.running_json) model_config = endpoint_json.get("model_config", {}) model_name = model_config.get("model_name", None) @@ -345,6 +357,7 @@ def monitor_slave_endpoint_status(self): model_id = model_config.get("model_id", None) endpoint_name = endpoint_json.get("end_point_name", None) + # Get replicas deployment result inside this device deployment_result = FedMLModelDatabase.get_instance().get_deployment_result_with_device_id( job.job_id, endpoint_name, model_name, job.edge_id) if deployment_result is None: @@ -434,7 +447,7 @@ def monitor_slave_endpoint_status(self): def _check_and_reset_endpoint_status( self, endpoint_id, device_id, deployment_result, only_check_inference_ready_status=False, - should_release_gpu_ids=True + should_release_gpu_ids=False ): result_json = deployment_result inference_url = result_json.get("model_url", None) @@ -464,23 +477,22 @@ def _check_and_reset_endpoint_status( return True # If the endpoint unavailable counter is greater than the threshold value, - # then release gpu ids and report failed status to the master agent. + # then try restarting the endpoint and release the gpu ids. + # If should_release_gpu_ids is True, then release the gpu ids. if self.endpoint_unavailable_counter.get(str(endpoint_id), 0) > \ SchedulerConstants.ENDPOINT_FAIL_THRESHOLD_VALUE: if not self.released_endpoints.get(str(endpoint_id), False) and should_release_gpu_ids: self.released_endpoints[str(endpoint_id)] = True - # Release the gpu ids print( - f"[endpoint/device][{endpoint_id}/{device_id}] Release gpu resource when the worker endpoint is not ready on monitoring periodically.") + f"[endpoint/device][{endpoint_id}/{device_id}] Release gpu resource " + f"when the worker endpoint is not ready on monitoring periodically.") JobRunnerUtils.get_instance().release_gpu_ids(endpoint_id, device_id) return False time.sleep(2) - return False - - def is_inference_ready(self, inference_url, timeout=None, device_id=None, endpoint_id=None): + def is_inference_ready(self, inference_url, timeout=None, device_id=None, endpoint_id=None, use_mqtt=False): response_ok = asyncio.run(FedMLHttpInference.is_inference_ready(inference_url, timeout=timeout)) if response_ok: print("Use http health check.") @@ -500,6 +512,9 @@ def is_inference_ready(self, inference_url, timeout=None, device_id=None, endpoi return response_ok print("Use http proxy health check failed.") + if not use_mqtt: + return False + agent_config = dict() agent_config["mqtt_config"] = dict() agent_config["mqtt_config"]["BROKER_HOST"] = self.mqtt_config["BROKER_HOST"] @@ -572,7 +587,7 @@ def _check_all_slave_endpoint_status(self, endpoint_id, endpoint_name, model_nam result_list = FedMLModelCache.get_instance().get_deployment_result_list( endpoint_id, endpoint_name, model_name) for result_item in result_list: - result_device_id, result_payload = FedMLModelCache.get_instance().get_result_item_info( + result_device_id, _, result_payload = FedMLModelCache.get_instance().get_result_item_info( result_item) # Check if the endpoint is activated @@ -687,10 +702,10 @@ def monitor_endpoint_logs(self): if count >= 1000: break - log_virtual_edge_id = int(job.edge_id) * 2 + # [Deprecated] log_virtual_edge_id = int(job.edge_id) * 2 if job.status == device_client_constants.ClientConstants.MSG_MLOPS_CLIENT_STATUS_FAILED or \ job.status == device_client_constants.ClientConstants.MSG_MLOPS_CLIENT_STATUS_KILLED: - MLOpsRuntimeLogDaemon.get_instance(fedml_args).stop_log_processor(job.job_id, log_virtual_edge_id) + MLOpsRuntimeLogDaemon.get_instance(fedml_args).stop_log_processor(job.job_id, int(job.edge_id)) continue if job.status != device_client_constants.ClientConstants.MSG_MLOPS_CLIENT_STATUS_FINISHED: @@ -707,7 +722,7 @@ def monitor_endpoint_logs(self): endpoint_name = endpoint_json.get("end_point_name", None) log_file_path, program_prefix = MLOpsRuntimeLog.build_log_file_path_with_run_params( - job.job_id, log_virtual_edge_id, device_server_constants.ServerConstants.get_log_file_dir(), is_server=True, + job.job_id, int(job.edge_id), device_server_constants.ServerConstants.get_log_file_dir(), is_server=True, log_file_prefix=JobMonitor.ENDPOINT_CONTAINER_LOG_PREFIX, ) @@ -728,20 +743,26 @@ def monitor_endpoint_logs(self): continue is_job_container_running = True - # Write container logs to the log file + # Rewrite container logs to the log file if i == 0: with open(log_file_path, "w") as f: - f.write(endpoint_logs) + pass + # f.write(f"[FedML Log Service] [Device {job.edge_id}] [Rank {i}] Start.\n") + # f.write(endpoint_logs) + # f.write(f"[FedML Log Service] [Device {job.edge_id}] [Rank {i}] End.\n") else: with open(log_file_path, "a") as f: - f.write(endpoint_logs) + pass + # f.write(f"[FedML Log Service] [Device {job.edge_id}] [Rank {i}] Start.\n") + # f.write(endpoint_logs) + # f.write(f"[FedML Log Service] [Device {job.edge_id}] [Rank {i}] End.\n") if is_job_container_running and not MLOpsRuntimeLogDaemon.get_instance(fedml_args). \ - is_log_processor_running(job.job_id, log_virtual_edge_id): + is_log_processor_running(job.job_id, int(job.edge_id)): setattr(fedml_args, "log_file_dir", os.path.dirname(log_file_path)) MLOpsRuntimeLogDaemon.get_instance(fedml_args).log_file_dir = os.path.dirname(log_file_path) MLOpsRuntimeLogDaemon.get_instance(fedml_args).start_log_processor( - job.job_id, log_virtual_edge_id, + job.job_id, int(job.edge_id), log_source=device_client_constants.ClientConstants.FEDML_LOG_SOURCE_TYPE_MODEL_END_POINT, log_file_prefix=JobMonitor.ENDPOINT_CONTAINER_LOG_PREFIX ) diff --git a/python/fedml/computing/scheduler/comm_utils/job_utils.py b/python/fedml/computing/scheduler/comm_utils/job_utils.py index d8dd8e00b7..3c871af6db 100644 --- a/python/fedml/computing/scheduler/comm_utils/job_utils.py +++ b/python/fedml/computing/scheduler/comm_utils/job_utils.py @@ -101,6 +101,14 @@ def occupy_gpu_ids(self, run_id, request_gpu_num, device_id, inner_id=None, ComputeCacheManager.get_instance().get_gpu_cache().set_device_available_gpu_ids( device_id, available_gpu_ids) + # For a single run, could be scale up. So if existed such a key, should extend, not replace + existed_gpu_nums = ComputeCacheManager.get_instance().get_gpu_cache().get_device_run_num_gpus( + switchable_device_id, run_id) + if existed_gpu_nums is not None and int(existed_gpu_nums) > 0: + matched_gpu_num += int(existed_gpu_nums) + run_gpu_ids.extend(ComputeCacheManager.get_instance().get_gpu_cache().get_device_run_gpu_ids( + switchable_device_id, run_id)) + ComputeCacheManager.get_instance().get_gpu_cache().set_device_run_num_gpus(switchable_device_id, run_id, matched_gpu_num) @@ -167,6 +175,45 @@ def trim_unavailable_gpu_ids(gpu_ids) -> List[int]: trimmed_gpu_ids = list(set(available_gpu_ids) - set(unavailable_gpu_ids)) return trimmed_gpu_ids.copy() + def release_partial_job_gpu(self, run_id, device_id, release_gpu_ids): + """ + In the deployment phase, if scale in, we need to release the gpu ids for the partial job. + """ + ComputeCacheManager.get_instance().set_redis_params() + # Reversely find the master (launch) device id and release the gpu ids + with ComputeCacheManager.get_instance().lock( + ComputeCacheManager.get_instance().get_gpu_cache().get_run_lock_key(run_id) + ): + original_run_id = ComputeCacheManager.get_instance().get_gpu_cache().get_endpoint_run_id_map(run_id) + edge_device_id, model_master_device_id, model_slave_device_id = \ + ComputeCacheManager.get_instance().get_gpu_cache().get_edge_model_id_map(run_id) + if edge_device_id is None: + edge_device_id = device_id + + with ComputeCacheManager.get_instance().lock( + ComputeCacheManager.get_instance().get_gpu_cache().get_device_run_lock_key( + edge_device_id, JobRunnerUtils.STATIC_RUN_LOCK_KEY_SUFFIX) + ): + run_gpu_ids = ComputeCacheManager.get_instance().get_gpu_cache().get_device_run_gpu_ids(device_id, + run_id) + remain_gpu_ids = [gpu_id for gpu_id in run_gpu_ids if gpu_id not in release_gpu_ids] + + # update the available gpu ids + with ComputeCacheManager.get_instance().lock( + ComputeCacheManager.get_instance().get_gpu_cache().get_device_lock_key(edge_device_id) + ): + # set global available gpu ids + available_gpu_ids = ComputeCacheManager.get_instance().get_gpu_cache().get_device_available_gpu_ids( + edge_device_id) + available_gpu_ids.extend(release_gpu_ids.copy()) + available_gpu_ids = list(dict.fromkeys(available_gpu_ids)) + ComputeCacheManager.get_instance().get_gpu_cache().set_device_available_gpu_ids( + edge_device_id, available_gpu_ids) + + # set run gpu ids + ComputeCacheManager.get_instance().get_gpu_cache().set_device_run_gpu_ids( + device_id, run_id, remain_gpu_ids) + def release_gpu_ids(self, run_id, device_id): edge_device_id = None original_run_id = None diff --git a/python/fedml/computing/scheduler/comm_utils/security_utils.py b/python/fedml/computing/scheduler/comm_utils/security_utils.py index a142410438..0711d26c00 100755 --- a/python/fedml/computing/scheduler/comm_utils/security_utils.py +++ b/python/fedml/computing/scheduler/comm_utils/security_utils.py @@ -35,3 +35,7 @@ def get_api_key(): return api_key except Exception as e: return "" + + +if __name__ == '__main__': + save_api_key("your_api_key") diff --git a/python/fedml/computing/scheduler/model_scheduler/device_client_constants.py b/python/fedml/computing/scheduler/model_scheduler/device_client_constants.py index 9884711253..b5f3bf93e5 100644 --- a/python/fedml/computing/scheduler/model_scheduler/device_client_constants.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_client_constants.py @@ -104,6 +104,7 @@ class ClientConstants(object): MSG_MODELOPS_DEPLOYMENT_STATUS_UPDATING = "UPDATING" MSG_MODELOPS_DEPLOYMENT_STATUS_ROLLBACK = "ROLLBACK" MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED = "DEPLOYED" + MSG_MODELOPS_DEPLOYMENT_STATUS_DELETED = "DELETED" MODEL_REQUIRED_MODEL_CONFIG_FILE = "fedml_model_config.yaml" MODEL_REQUIRED_MODEL_BIN_FILE = "fedml_model.bin" diff --git a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py index e82e8c5542..b99e0bea58 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py @@ -23,6 +23,7 @@ import fedml from fedml import mlops from fedml.computing.scheduler.model_scheduler.device_model_msg_object import FedMLModelMsgObject +from fedml.computing.scheduler.scheduler_core.compute_utils import ComputeUtils from fedml.core.distributed.communication.s3.remote_storage import S3Storage from .device_model_cache import FedMLModelCache from ..comm_utils import sys_utils, security_utils @@ -51,6 +52,9 @@ from ..comm_utils.constants import SchedulerConstants from fedml.computing.scheduler.comm_utils.job_monitor import JobMonitor +from .device_replica_handler import FedMLDeviceReplicaHandler + +from fedml.computing.scheduler.scheduler_core.endpoint_sync_protocol import FedMLEndpointSyncProtocol class RunnerError(Exception): """ Runner failed. """ @@ -120,6 +124,8 @@ def __init__(self, args, edge_id=0, request_json=None, agent_config=None, run_id self.subscribed_topics = list() self.user_name = None + self.replica_handler = None + def unzip_file(self, zip_file, unzip_file_path) -> str: unziped_file_name = "" if zipfile.is_zipfile(zip_file): @@ -388,6 +394,8 @@ def run_impl(self): self.check_runner_stop_event() + # TODO: Reconcile update op here. + # update local config with real time parameters from server and dynamically replace variables value logging.info("download and unzip model to local...") unzip_package_path, model_bin_file, fedml_config_object = \ @@ -412,105 +420,223 @@ def run_impl(self): # download model net and load into the torch model model_from_open = None self.model_is_from_open = None - if self.model_is_from_open: - logging.info("process the model net from open...") - self.check_runner_stop_event() - s3_config = self.agent_config.get("s3_config", None) - if s3_config is not None and model_net_url is not None and model_net_url != "": - s3_client = S3Storage(s3_config) - url_parsed = urlparse(model_net_url) - path_list = url_parsed.path.split("/") - if len(path_list) > 0: - model_key = path_list[-1] - model_from_open = s3_client.read_model_net(model_key, - ClientConstants.get_model_cache_dir()) - - model_input_size, model_input_type = mlops.get_training_model_input_info(model_net_url, s3_config) - if model_input_size is not None and model_input_type is not None: - model_config_parameters["input_size"] = model_input_size - model_config_parameters["input_types"] = model_input_type - logging.info( - f"model input size {model_input_size}, input type {model_input_type} from the open platform.") - - logging.info("Check if need update / removing existed container...") - if "diff_devices" in self.request_json and str(self.edge_id) in self.request_json["diff_devices"] and \ - self.request_json["diff_devices"][str(self.edge_id)] == ClientConstants.DEVICE_DIFF_REPLACE_OPERATION: - self.handle_replaced_device() + + # logging.info("Check if need update / removing existed container...") + # if "diff_devices" in self.request_json and str(self.edge_id) in self.request_json["diff_devices"] and \ + # self.request_json["diff_devices"][str(self.edge_id)] == ClientConstants.DEVICE_DIFF_REPLACE_OPERATION: + # # self.handle_replaced_device() + # pass logging.info("start the model deployment...") self.check_runner_stop_event() running_model_name, inference_output_url, inference_model_version, model_metadata, model_config = \ "", "", model_version, {}, {} - try: - client_ip = self.get_ip_address(self.request_json) - running_model_name, inference_output_url, inference_model_version, model_metadata, model_config = \ - start_deployment( - inference_end_point_id, end_point_name, model_id, model_version, - unzip_package_path, model_bin_file, model_name, inference_engine, - ClientConstants.INFERENCE_HTTP_PORT, - ClientConstants.INFERENCE_GRPC_PORT, - ClientConstants.INFERENCE_METRIC_PORT, - use_gpu, memory_size, - ClientConstants.INFERENCE_CONVERTOR_IMAGE, - ClientConstants.INFERENCE_SERVER_IMAGE, - client_ip, - self.model_is_from_open, model_config_parameters, - model_from_open, - token, - master_ip, self.edge_id, master_device_id=device_ids[0]) - except Exception as e: - inference_output_url = "" - logging.error(f"Exception at deployment: {traceback.format_exc()}") - if inference_output_url == "": - logging.error("failed to deploy the model...") + # Reconcile the replica number (op: add, remove) + prev_rank, op, op_num = self.replica_handler.reconcile_num_replica() + + # Reconcile the replica version (op: update) + replica_rank_to_update = [] + if not op: + replica_rank_to_update, op = self.replica_handler.reconcile_replica_version() + + if not op: + logging.info("No need to reconcile.") + return True - result_payload = self.send_deployment_results( - end_point_name, self.edge_id, ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED, - model_id, model_name, inference_output_url, inference_model_version, inference_port, - inference_engine, model_metadata, model_config) + if op == "add": + worker_ip = self.get_ip_address(self.request_json) + for rank in range(prev_rank+1, prev_rank+1+op_num): + # TODO: Support Rollback if this for loop failed + try: + running_model_name, inference_output_url, inference_model_version, model_metadata, model_config = \ + start_deployment( + inference_end_point_id, end_point_name, model_id, model_version, + unzip_package_path, model_bin_file, model_name, inference_engine, + ClientConstants.INFERENCE_HTTP_PORT, + ClientConstants.INFERENCE_GRPC_PORT, + ClientConstants.INFERENCE_METRIC_PORT, + use_gpu, memory_size, + ClientConstants.INFERENCE_CONVERTOR_IMAGE, + ClientConstants.INFERENCE_SERVER_IMAGE, + worker_ip, + self.model_is_from_open, model_config_parameters, + model_from_open, + token, + master_ip, self.edge_id, master_device_id=device_ids[0], replica_rank=rank) + except Exception as e: + inference_output_url = "" + logging.error(f"Exception at deployment: {traceback.format_exc()}") + + if inference_output_url == "": + logging.error("failed to deploy the model...") + + result_payload = self.send_deployment_results( + end_point_name, self.edge_id, ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED, + model_id, model_name, inference_output_url, inference_model_version, inference_port, + inference_engine, model_metadata, model_config) + + self.mlops_metrics.run_id = self.run_id + self.mlops_metrics.broadcast_client_training_status( + self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_FAILED, + is_from_model=True, run_id=self.run_id) + + self.mlops_metrics.client_send_exit_train_msg( + run_id, self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_FAILED) + + # After sending the deployment status, we should wait for the master to delete the deployment status + status_payload = self.send_deployment_status( + end_point_name, self.edge_id, model_id, model_name, model_version, inference_output_url, + ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED, inference_port=inference_port, + replica_no=rank + 1) + + return False + else: + logging.info("finished deployment, continue to send results to master...") + result_payload = self.send_deployment_results( + end_point_name, self.edge_id, ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED, + model_id, model_name, inference_output_url, model_version, inference_port_external, + inference_engine, model_metadata, model_config, replica_no=rank + 1) + + if inference_port_external != inference_port: # Save internal port to local db + logging.info("inference_port_external {} != inference_port {}".format( + inference_port_external, inference_port)) + result_payload = self.construct_deployment_results( + end_point_name, self.edge_id, ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED, + model_id, model_name, inference_output_url, model_version, inference_port, + inference_engine, model_metadata, model_config, replica_no=rank + 1) + + FedMLModelDatabase.get_instance().set_deployment_result( + run_id, end_point_name, model_name, model_version, self.edge_id, + json.dumps(result_payload), replica_no=rank + 1) + + logging.info(f"Deploy replica {rank+1} / {prev_rank+1+op_num} successfully.") + time.sleep(5) + time.sleep(1) self.mlops_metrics.run_id = self.run_id self.mlops_metrics.broadcast_client_training_status( - self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_FAILED, + self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_FINISHED, is_from_model=True, run_id=self.run_id) + return True + elif op == "remove": + for rank_to_delete in range(prev_rank, prev_rank-op_num, -1): + self.replica_handler.remove_replica(rank_to_delete) - self.mlops_metrics.client_send_exit_train_msg( - run_id, self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_FAILED) + FedMLModelCache.get_instance().set_redis_params() + replica_occupied_gpu_ids_str = FedMLModelCache.get_instance().get_replica_gpu_ids( + run_id, end_point_name, model_name, self.edge_id, rank_to_delete+1) - # After sending the deployment status, we should wait for the master to delete the deployment status - status_payload = self.send_deployment_status( - end_point_name, self.edge_id, model_id, model_name, model_version, inference_output_url, - ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED, inference_port=inference_port) + replica_occupied_gpu_ids = json.loads(replica_occupied_gpu_ids_str) - return False - else: - logging.info("finished deployment, continue to send results to master...") - status_payload = self.send_deployment_status( # Send Master the external port - end_point_name, self.edge_id, model_id, model_name, model_version, inference_output_url, - ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED, inference_port=inference_port_external) - result_payload = self.send_deployment_results( - end_point_name, self.edge_id, ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED, - model_id, model_name, inference_output_url, model_version, inference_port_external, - inference_engine, model_metadata, model_config) - - if inference_port_external != inference_port: # For Worker, use internal port - logging.info("inference_port_external {} != inference_port {}".format( - inference_port_external, inference_port)) - status_payload = self.construct_deployment_status( - end_point_name, self.edge_id, model_id, model_name, model_version, inference_output_url, - ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED, inference_port=inference_port) - result_payload = self.construct_deployment_results( - end_point_name, self.edge_id, ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED, - model_id, model_name, inference_output_url, model_version, inference_port, - inference_engine, model_metadata, model_config) - - FedMLModelDatabase.get_instance().set_deployment_result( - run_id, end_point_name, model_name, model_version, self.edge_id, json.dumps(result_payload)) - - FedMLModelDatabase.get_instance().set_deployment_status( - run_id, end_point_name, model_name, model_version, self.edge_id, json.dumps(status_payload)) + JobRunnerUtils.get_instance().release_partial_job_gpu(run_id, self.edge_id, replica_occupied_gpu_ids) + + FedMLModelDatabase.get_instance().delete_deployment_result_with_device_id_and_rank( + run_id, end_point_name, model_name, self.edge_id, rank_to_delete) + + # Report the deletion msg to master + result_payload = self.send_deployment_results( + end_point_name, self.edge_id, ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DELETED, + model_id, model_name, inference_output_url, model_version, inference_port_external, + inference_engine, model_metadata, model_config, replica_no=rank_to_delete + 1) + + time.sleep(1) + self.mlops_metrics.run_id = self.run_id + self.mlops_metrics.broadcast_client_training_status( + self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_FINISHED, + is_from_model=True, run_id=self.run_id) + # TODO: If delete all replica, then delete the job and related resources + if rank_to_delete == 0: + pass + return True + elif op == "update": + # Update is combine of delete and add + worker_ip = self.get_ip_address(self.request_json) + for rank in replica_rank_to_update: + # Delete the container + self.replica_handler.remove_replica(rank) + + FedMLModelCache.get_instance().set_redis_params() + replica_occupied_gpu_ids_str = FedMLModelCache.get_instance().get_replica_gpu_ids( + run_id, end_point_name, model_name, self.edge_id, rank + 1) + + replica_occupied_gpu_ids = json.loads(replica_occupied_gpu_ids_str) + + JobRunnerUtils.get_instance().release_partial_job_gpu(run_id, self.edge_id, replica_occupied_gpu_ids) + + # Delete the deployment result from local db + FedMLModelDatabase.get_instance().delete_deployment_result_with_device_id_and_rank( + run_id, end_point_name, model_name, self.edge_id, rank) + + time.sleep(1) + + # Add the container + # TODO: Reduce the duplicated code + try: + running_model_name, inference_output_url, inference_model_version, model_metadata, model_config = \ + start_deployment( + inference_end_point_id, end_point_name, model_id, model_version, + unzip_package_path, model_bin_file, model_name, inference_engine, + ClientConstants.INFERENCE_HTTP_PORT, + ClientConstants.INFERENCE_GRPC_PORT, + ClientConstants.INFERENCE_METRIC_PORT, + use_gpu, memory_size, + ClientConstants.INFERENCE_CONVERTOR_IMAGE, + ClientConstants.INFERENCE_SERVER_IMAGE, + worker_ip, + self.model_is_from_open, model_config_parameters, + model_from_open, + token, + master_ip, self.edge_id, master_device_id=device_ids[0], replica_rank=rank) + except Exception as e: + inference_output_url = "" + logging.error(f"Exception at deployment: {traceback.format_exc()}") + + if inference_output_url == "": + logging.error("failed to deploy the model...") + + result_payload = self.send_deployment_results( + end_point_name, self.edge_id, ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED, + model_id, model_name, inference_output_url, inference_model_version, inference_port, + inference_engine, model_metadata, model_config) + + self.mlops_metrics.run_id = self.run_id + self.mlops_metrics.broadcast_client_training_status( + self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_FAILED, + is_from_model=True, run_id=self.run_id) + + self.mlops_metrics.client_send_exit_train_msg( + run_id, self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_FAILED) + + # After sending the deployment status, we should wait for the master to delete the deployment status + status_payload = self.send_deployment_status( + end_point_name, self.edge_id, model_id, model_name, model_version, inference_output_url, + ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED, inference_port=inference_port, + replica_no=rank + 1) + + return False + else: + logging.info("finished deployment, continue to send results to master...") + result_payload = self.send_deployment_results( + end_point_name, self.edge_id, ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED, + model_id, model_name, inference_output_url, model_version, inference_port_external, + inference_engine, model_metadata, model_config, replica_no=rank + 1) + + if inference_port_external != inference_port: # Save internal port to local db + logging.info("inference_port_external {} != inference_port {}".format( + inference_port_external, inference_port)) + result_payload = self.construct_deployment_results( + end_point_name, self.edge_id, ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED, + model_id, model_name, inference_output_url, model_version, inference_port, + inference_engine, model_metadata, model_config, replica_no=rank + 1) + + FedMLModelDatabase.get_instance().set_deployment_result( + run_id, end_point_name, model_name, model_version, self.edge_id, + json.dumps(result_payload), replica_no=rank + 1) + + logging.info(f"Update replica with no {rank + 1} successfully. Op num {op_num}") + time.sleep(5) time.sleep(1) self.mlops_metrics.run_id = self.run_id self.mlops_metrics.broadcast_client_training_status( @@ -518,6 +644,11 @@ def run_impl(self): is_from_model=True, run_id=self.run_id) return True + else: + # The delete op will be handled by callback_delete_deployment + logging.error(f"Unsupported op {op} with op num {op_num}") + return False + def handle_replaced_device(self): """ Strategy-1: @@ -559,7 +690,7 @@ def handle_replaced_device(self): def construct_deployment_results(self, end_point_name, device_id, model_status, model_id, model_name, model_inference_url, model_version, inference_port, inference_engine, - model_metadata, model_config): + model_metadata, model_config, replica_no=1): deployment_results_payload = {"end_point_id": self.run_id, "end_point_name": end_point_name, "model_id": model_id, "model_name": model_name, "model_url": model_inference_url, "model_version": model_version, @@ -568,31 +699,37 @@ def construct_deployment_results(self, end_point_name, device_id, model_status, "model_metadata": model_metadata, "model_config": model_config, "model_status": model_status, - "inference_port": inference_port} + "inference_port": inference_port, + "replica_no": replica_no, + } return deployment_results_payload def construct_deployment_status(self, end_point_name, device_id, model_id, model_name, model_version, model_inference_url, model_status, - inference_port=ClientConstants.MODEL_INFERENCE_DEFAULT_PORT): + inference_port=ClientConstants.MODEL_INFERENCE_DEFAULT_PORT, + replica_no=1, # start from 1 + ): deployment_status_payload = {"end_point_id": self.run_id, "end_point_name": end_point_name, "device_id": device_id, "model_id": model_id, "model_name": model_name, "model_version": model_version, "model_url": model_inference_url, "model_status": model_status, - "inference_port": inference_port} + "inference_port": inference_port, + "replica_no": replica_no, + } return deployment_status_payload def send_deployment_results(self, end_point_name, device_id, model_status, model_id, model_name, model_inference_url, model_version, inference_port, inference_engine, - model_metadata, model_config): + model_metadata, model_config, replica_no=1): deployment_results_topic = "model_device/model_device/return_deployment_result/{}".format(device_id) deployment_results_payload = self.construct_deployment_results( end_point_name, device_id, model_status, model_id, model_name, model_inference_url, model_version, inference_port, inference_engine, - model_metadata, model_config) + model_metadata, model_config, replica_no=replica_no) logging.info("[client] send_deployment_results: topic {}, payload {}.".format(deployment_results_topic, deployment_results_payload)) @@ -602,13 +739,16 @@ def send_deployment_results(self, end_point_name, device_id, model_status, def send_deployment_status(self, end_point_name, device_id, model_id, model_name, model_version, model_inference_url, model_status, - inference_port=ClientConstants.MODEL_INFERENCE_DEFAULT_PORT): + inference_port=ClientConstants.MODEL_INFERENCE_DEFAULT_PORT, + replica_no=1, # start from 1 + ): deployment_status_topic = "model_device/model_device/return_deployment_status/{}".format(device_id) deployment_status_payload = self.construct_deployment_status( end_point_name, device_id, model_id, model_name, model_version, model_inference_url, model_status, - inference_port=inference_port) + inference_port=inference_port, + replica_no=replica_no) logging.info("[client] send_deployment_status: topic {}, payload {}.".format(deployment_status_topic, deployment_status_payload)) @@ -806,6 +946,11 @@ def callback_start_deployment(self, topic, payload): self.run_process_completed_event_map[run_id_str].clear() client_runner.run_process_completed_event = self.run_process_completed_event_map[run_id_str] self.model_runner_mapping[run_id_str] = client_runner + + # Replica Handler is per deployment! + replica_handler = FedMLDeviceReplicaHandler(self.edge_id, self.request_json) + client_runner.replica_handler = replica_handler + self.run_id = run_id self.run_process_map[run_id_str] = Process(target=client_runner.run, args=( self.run_process_event_map[run_id_str], self.run_process_completed_event_map[run_id_str] diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py b/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py index 9a997a80e2..a58334a477 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py @@ -18,6 +18,11 @@ class FedMLModelCache(Singleton): FEDML_MODEL_DEVICE_INFO_TAG = "FEDML_MODEL_DEVICE_INFO_TAG-" FEDML_MODEL_END_POINT_TOKEN_TAG = "FEDML_MODEL_END_POINT_TOKEN_TAG-" FEDML_MODEL_ROUND_ROBIN_PREVIOUS_DEVICE_TAG = "FEDML_MODEL_ROUND_ROBIN_PREVIOUS_DEVICE_TAG-" + FEDML_MODEL_ENDPOINT_REPLICA_NUM_TAG = "FEDML_MODEL_ENDPOINT_REPLICA_NUM_TAG-" + + # On the worker + FEDML_MODEL_REPLICA_GPU_IDS_TAG = "FEDML_MODEL_REPLICA_GPU_IDS_TAG-" + FEDML_KEY_COUNT_PER_SCAN = 1000 def __init__(self): @@ -85,16 +90,16 @@ def get_instance(redis_addr="local", redis_port=6379): return FedMLModelCache() def set_deployment_result(self, end_point_id, end_point_name, - model_name, model_version, device_id, deployment_result): - result_dict = {"cache_device_id": device_id, "result": deployment_result} + model_name, model_version, device_id, deployment_result, replica_no): + result_dict = {"cache_device_id": device_id, "cache_replica_no": replica_no, "result": deployment_result} try: - # Delete old result + # Delete old result using (e_id, end_point_name, model_name, device_id, replica_no) # In this list, find the result's complete record, delete it. result_list = self.redis_connection.lrange( self.get_deployment_result_key(end_point_id, end_point_name, model_name), 0, -1) for result_item in result_list: - result_device_id, result_payload = self.get_result_item_info(result_item) - if result_device_id == device_id: + res_device_id, res_replica_no, res_payload = self.get_result_item_info(result_item) + if res_device_id == device_id and res_replica_no == replica_no: self.redis_connection.lrem( self.get_deployment_result_key(end_point_id, end_point_name, model_name), 0, result_item) @@ -105,18 +110,20 @@ def set_deployment_result(self, end_point_id, end_point_name, pass self.model_deployment_db.set_deployment_result(end_point_id, end_point_name, model_name, model_version, - device_id, deployment_result) + device_id, deployment_result, replica_no) def set_deployment_status(self, end_point_id, end_point_name, - model_name, model_version, device_id, deployment_status): + model_name, model_version, device_id, deployment_status, replica_no): status_dict = {"cache_device_id": device_id, "status": deployment_status} try: - self.redis_connection.rpush(self.get_deployment_status_key(end_point_id, end_point_name, model_name), json.dumps(status_dict)) + # rpush could tolerate the same e_id, d_id with different r_no + self.redis_connection.rpush(self.get_deployment_status_key(end_point_id, end_point_name, model_name), + json.dumps(status_dict)) except Exception as e: pass self.model_deployment_db.set_deployment_status(end_point_id, end_point_name, model_name, model_version, - device_id, deployment_status) + device_id, deployment_status, replica_no) def delete_deployment_status(self, element: str, end_point_id, end_point_name, model_name): self.redis_connection.lrem(self.get_deployment_status_key(end_point_id, end_point_name, model_name), @@ -131,10 +138,32 @@ def delete_deployment_result(self, element: str, end_point_id, end_point_name, m except Exception as e: pass + def delete_deployment_result_with_device_id_and_replica_no(self, end_point_id, end_point_name, model_name, + device_id, replica_no_to_delete): + result_item_found = None + + result_list = self.get_deployment_result_list( + end_point_id, end_point_name, model_name) + + for result_item in result_list: + cache_device_id, cache_replica_no, result_payload = ( + self.get_result_item_info(result_item)) + + if str(cache_device_id) == str(device_id) and cache_replica_no == replica_no_to_delete: + result_item_found = result_item + break + + # Delete the replica element + if result_item_found is not None: + self.delete_deployment_result( + result_item_found, end_point_id, end_point_name, model_name) + def get_deployment_result_list(self, end_point_id, end_point_name, model_name): try: - result_list = self.redis_connection.lrange(self.get_deployment_result_key(end_point_id, end_point_name, model_name), 0, -1) + result_list = self.redis_connection.lrange( + self.get_deployment_result_key(end_point_id, end_point_name, model_name), 0, -1) except Exception as e: + logging.info(e) result_list = None if result_list is None or len(result_list) <= 0: @@ -144,13 +173,14 @@ def get_deployment_result_list(self, end_point_id, end_point_name, model_name): self.redis_connection.rpush(self.get_deployment_result_key(end_point_id, end_point_name, model_name), json.dumps(result)) except Exception as e: + logging.info(e) pass return result_list def delete_deployment_result(self, element: str, end_point_id, end_point_name, model_name): self.redis_connection.lrem(self.get_deployment_result_key(end_point_id, end_point_name, model_name), 0, element) - device_id, _ = self.get_result_item_info(element) + device_id, _, _ = self.get_result_item_info(element) self.model_deployment_db.delete_deployment_result(device_id, end_point_id, end_point_name, model_name) def get_deployment_result_list_size(self, end_point_id, end_point_name, model_name): @@ -192,50 +222,42 @@ def get_result_item_info(self, result_item): result_item_json = json.loads(result_item) if isinstance(result_item_json, str): result_item_json = json.loads(result_item_json) + device_id = result_item_json["cache_device_id"] + replica_no = result_item_json["cache_replica_no"] + if isinstance(result_item_json["result"], str): result_payload = json.loads(result_item_json["result"]) else: result_payload = result_item_json["result"] - return device_id, result_payload + return device_id, replica_no, result_payload def get_idle_device(self, end_point_id, end_point_name, model_name, model_version, check_end_point_status=True): - # Find all deployed devices - try: - status_list = self.get_deployment_status_list(end_point_id, end_point_name, model_name) # DEPLOYMENT_STATUS - except Exception as e: - logging.error(f"get_deployment_status_list failed {e}") - return None, None + # Deprecated the model status logic, query directly from the deployment result list + idle_device_list = list() - if len(status_list) == 0: - return None, None + result_list = self.get_deployment_result_list(end_point_id, end_point_name, model_name) - idle_device_list = list() - if model_version == "latest": - model_version = self.get_latest_version(status_list) - logging.info(f"model_version {model_version}") + for result_item in result_list: + device_id, _, result_payload = self.get_result_item_info(result_item) + found_end_point_id = result_payload["end_point_id"] + found_end_point_name = result_payload["end_point_name"] + found_model_name = result_payload["model_name"] + found_model_version = result_payload["model_version"] + + logging.info(result_payload["model_status"]) + + if (str(found_end_point_id) == str(end_point_id) and found_end_point_name == end_point_name and + found_model_name == model_name and + (found_model_version == model_version or model_version == "*")): + if "model_status" in result_payload and result_payload["model_status"] == "DEPLOYED": + idle_device_list.append({"device_id": device_id, "end_point_id": end_point_id}) - # iterate all devices, find those with correct version and deployed - for status_item in status_list: - try: - device_id, status_payload = self.get_status_item_info(status_item) - logging.info(f"status_payload {status_payload}") - model_status = status_payload["model_status"] - model_version_cached = status_payload["model_version"] - end_point_id_cache = status_payload["end_point_id"] - logging.info(f"model_version {model_version}, model_version_cache {model_version_cached}") - if (model_version == model_version_cached or model_version == "*") and \ - model_status == ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED: - idle_device_list.append({"device_id": device_id, "end_point_id": end_point_id_cache}) - except Exception as e: - logging.info(f"Get idle device list Failed: {e}, status_item {status_item}") - pass - if len(idle_device_list) <= 0: - return None, None logging.info(f"{len(idle_device_list)} devices has this model on it: {idle_device_list}") - # Randomly shuffle + + # # Randomly shuffle # shuffle the list of deployed devices and get the first one as the target idle device. # if len(idle_device_list) <= 0: # return None, None @@ -271,18 +293,17 @@ def get_idle_device(self, end_point_id, end_point_name, # Find deployment result from the target idle device. try: - result_list = self.get_deployment_result_list(end_point_id, end_point_name, model_name) for result_item in result_list: - device_id, result_payload = self.get_result_item_info(result_item) + logging.info("enter the for loop") + device_id, _, result_payload = self.get_result_item_info(result_item) found_end_point_id = result_payload["end_point_id"] found_end_point_name = result_payload["end_point_name"] - # Check whether the end point is activated. - if check_end_point_status: - end_point_activated = self.get_end_point_activation(found_end_point_id) - if not end_point_activated: - continue + found_model_status = result_payload["model_status"] - if found_end_point_id == idle_device_dict["end_point_id"] \ + if found_model_status != "DEPLOYED": + continue + + if str(found_end_point_id) == str(idle_device_dict["end_point_id"]) \ and device_id == idle_device_dict["device_id"]: if same_model_device_rank > 0: same_model_device_rank -= 1 @@ -316,10 +337,13 @@ def get_latest_version(self, status_list): return latest_version def get_deployment_result_with_device_id(self, end_point_id, end_point_name, model_name, device_id): + """" + TODO: Return multiple replicas' result for the same device_id + """ try: result_list = self.get_deployment_result_list(end_point_id, end_point_name, model_name) for result_item in result_list: - result_device_id, result_payload = self.get_result_item_info(result_item) + result_device_id, _, result_payload = self.get_result_item_info(result_item) found_end_point_id = result_payload["end_point_id"] end_point_activated = self.get_end_point_activation(found_end_point_id) @@ -363,6 +387,26 @@ def set_end_point_activation(self, end_point_id, end_point_name, activate_status pass self.model_deployment_db.set_end_point_activation(end_point_id, end_point_name, status) + def set_replica_gpu_ids(self, end_point_id, end_point_name, model_name, device_id, replica_no, gpu_ids): + # Convert the list to string + try: + self.redis_connection.set(self.get_replica_gpu_ids_key(end_point_id, end_point_name, + model_name, device_id, replica_no), str(gpu_ids)) + except Exception as e: + print(e) + logging.error(e) + + # TODO: Use Sqlite for the replica backup + + def get_replica_gpu_ids(self, end_point_id, end_point_name, model_name, device_id, replica_no): + try: + if self.redis_connection.exists(self.get_replica_gpu_ids_key(end_point_id, end_point_name, + model_name, device_id, replica_no)): + return self.redis_connection.get(self.get_replica_gpu_ids_key(end_point_id, end_point_name, + model_name, device_id, replica_no)) + except Exception as e: + pass + def delete_end_point(self, end_point_id, end_point_name, model_name, model_version): try: print("Will Delete the realated redis keys permanently") @@ -378,26 +422,12 @@ def delete_end_point(self, end_point_id, end_point_name, model_name, model_versi pass def get_end_point_activation(self, end_point_id): - status_int = -1 - try: - if self.redis_connection.exists(self.get_end_point_activation_key(end_point_id)): - status_int = self.redis_connection.get(self.get_end_point_activation_key(end_point_id)) - except Exception as e: - pass - - if status_int == -1: - status_int = self.model_deployment_db.get_end_point_activation(end_point_id) - try: - self.redis_connection.set(self.get_end_point_activation_key(end_point_id), status_int) - except Exception as e: - pass - - status = True if int(status_int) == 1 else False - return status + # [Deprecated] activation logic is removed + return True def get_end_point_full_key_by_id(self, end_point_id): - # e.g. FEDML_MODEL_DEPLOYMENT_STATUS--1234-dummy_endpoint_name-dummy_model_name - target_prefix = f"{FedMLModelCache.FEDML_MODEL_DEPLOYMENT_STATUS_TAG}-{end_point_id}-*" + # e.g. FEDML_MODEL_DEPLOYMENT_RESULT--1234-dummy_endpoint_name-dummy_model_name + target_prefix = f"{FedMLModelCache.FEDML_MODEL_DEPLOYMENT_RESULT_TAG}-{end_point_id}-*" status_list = list() for key in self.redis_connection.scan_iter(target_prefix): status_list.append(key) @@ -497,6 +527,19 @@ def get_end_point_token(self, end_point_id, end_point_name, model_name): return token + def get_endpoint_devices_replica_num(self, end_point_id): + """ + Return a endpoint_devices_replica_num dict {id1: 1, id2: 1}, if not exist, return None + """ + try: + replica_num = self.redis_connection.get( + self.get_endpoint_replica_num_key(end_point_id)) + except Exception as e: + replica_num = None + # TODO: Use Sqlite for the replica backup + + return replica_num + def get_deployment_result_key(self, end_point_id, end_point_name, model_name): return "{}-{}-{}-{}".format(FedMLModelCache.FEDML_MODEL_DEPLOYMENT_RESULT_TAG, end_point_id, end_point_name, model_name) @@ -518,6 +561,14 @@ def get_deployment_token_key(self, end_point_id, end_point_name, model_name): def get_round_robin_prev_device(self, end_point_id, end_point_name, model_name, version): return "{}-{}-{}-{}-{}".format(FedMLModelCache.FEDML_MODEL_ROUND_ROBIN_PREVIOUS_DEVICE_TAG, end_point_id, end_point_name, model_name, version) + def get_endpoint_replica_num_key(self, end_point_id): + return "{}-{}-{}-{}-{}".format(FedMLModelCache.FEDML_MODEL_ENDPOINT_REPLICA_NUM_TAG, end_point_id, "replica_num", "key") + + @staticmethod + def get_replica_gpu_ids_key(end_point_id, end_point_name, model_name, device_id, replica_no): + return "{}-{}-{}-{}-{}-{}".format(FedMLModelCache.FEDML_MODEL_REPLICA_GPU_IDS_TAG, end_point_id, + end_point_name, model_name, device_id, replica_no) + def set_monitor_metrics(self, end_point_id, end_point_name, model_name, model_version, total_latency, avg_latency, diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_db.py b/python/fedml/computing/scheduler/model_scheduler/device_model_db.py index e11e098caf..6ee7af1cdd 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_db.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_db.py @@ -31,20 +31,25 @@ def set_database_base_dir(self, database_base_dir): self.db_base_dir = database_base_dir def set_deployment_result(self, end_point_id, end_point_name, model_name, model_version, - device_id, deployment_result): + device_id, deployment_result, replica_no): self.set_deployment_results_info(end_point_id, end_point_name, model_name, model_version, - device_id, deployment_result=deployment_result) + device_id, deployment_result=deployment_result, replica_no=replica_no) def set_deployment_status(self, end_point_id, end_point_name, model_name, model_version, - device_id, deployment_status): + device_id, deployment_status, replica_no): self.set_deployment_results_info(end_point_id, end_point_name, model_name, model_version, - device_id, deployment_status=deployment_status) + device_id, deployment_status=deployment_status, replica_no=replica_no) def get_deployment_result_list(self, end_point_id, end_point_name, model_name, model_version=None): + """ + query from sqlite db using e_id + """ result_list = self.get_deployment_results_info(end_point_id, end_point_name, model_name, model_version) ret_result_list = list() for result in result_list: - result_dict = {"cache_device_id": result.device_id, "result": result.deployment_result} + result_dict = {"cache_device_id": result.device_id, + "cache_replica_no": result.replica_no, + "result": result.deployment_result} ret_result_list.append(json.dumps(result_dict)) return ret_result_list @@ -58,18 +63,24 @@ def get_deployment_status_list(self, end_point_id, end_point_name, model_name, m return ret_status_list def get_deployment_result_with_device_id(self, end_point_id, end_point_name, model_name, device_id): + """ + Return a list of replica's result given end_point_id, end_point_name, model_name, device_id + """ + replica_result_list = list() try: result_list = self.get_deployment_result_list(end_point_id, end_point_name, model_name) for result_item in result_list: - result_device_id, result_payload = self.get_result_item_info(result_item) + result_device_id, _, result_payload = self.get_result_item_info(result_item) found_end_point_id = result_payload["end_point_id"] if str(found_end_point_id) == str(end_point_id) and str(result_device_id) == str(device_id): - return result_payload + replica_result_list.append(result_payload) except Exception as e: - logging.info(e) + # Do not intervene other endpoints on this device + logging.error(f"Error in get_deployment_result_with_device_id: {e}") + return None - return None + return replica_result_list def get_deployment_status_with_device_id(self, end_point_id, end_point_name, model_name, device_id): try: @@ -124,6 +135,18 @@ def delete_deployment_result_with_device_id(self, end_point_id, end_point_name, FedMLDeploymentResultInfoModel.device_id == f'{device_id}')).delete() self.db_connection.commit() + def delete_deployment_result_with_device_id_and_rank(self, end_point_id, end_point_name, model_name, + device_id, replica_rank): + replica_no = replica_rank + 1 + self.open_job_db() + self.db_connection.query(FedMLDeploymentResultInfoModel).filter( + and_(FedMLDeploymentResultInfoModel.end_point_id == f'{end_point_id}', + FedMLDeploymentResultInfoModel.end_point_name == f'{end_point_name}', + FedMLDeploymentResultInfoModel.model_name == f'{model_name}', + FedMLDeploymentResultInfoModel.device_id == f'{device_id}', + FedMLDeploymentResultInfoModel.replica_no == f'{replica_no}')).delete() + self.db_connection.commit() + def delete_deployment_run_info(self, end_point_id): # db / table -> model-deployment.db / "deployment_run_info" self.open_job_db() @@ -136,11 +159,13 @@ def get_result_item_info(self, result_item): if isinstance(result_item_json, dict): result_item_json = json.loads(result_item) device_id = result_item_json["cache_device_id"] + replica_no = result_item_json["cache_replica_no"] + if isinstance(result_item_json["result"], str): result_payload = json.loads(result_item_json["result"]) else: result_payload = result_item_json["result"] - return device_id, result_payload + return device_id, replica_no, result_payload def get_status_item_info(self, status_item): status_item_json = json.loads(status_item) @@ -274,17 +299,19 @@ def get_deployment_results_info(self, end_point_id, end_point_name, model_name, def set_deployment_results_info(self, end_point_id, end_point_name, model_name, model_version, device_id, - deployment_result=None, deployment_status=None): - ''' - end_point_id + device_id is unique identifier, + deployment_result=None, deployment_status=None, replica_no=None): + """ + end_point_id + device_id + replica_no is unique identifier, we do not allow duplicate records - ''' + """ self.open_job_db() result_info = self.db_connection.query(FedMLDeploymentResultInfoModel). \ filter(and_(FedMLDeploymentResultInfoModel.end_point_id == f'{end_point_id}', FedMLDeploymentResultInfoModel.end_point_name == f'{end_point_name}', FedMLDeploymentResultInfoModel.model_name == f'{model_name}', - FedMLDeploymentResultInfoModel.device_id == f'{device_id}')).first() + FedMLDeploymentResultInfoModel.device_id == f'{device_id}', + FedMLDeploymentResultInfoModel.replica_no == f'{replica_no}' + )).first() # Insert if result_info is None: result_info = FedMLDeploymentResultInfoModel(end_point_id=end_point_id, @@ -293,7 +320,9 @@ def set_deployment_results_info(self, end_point_id, end_point_name, model_version=model_version, device_id=device_id, deployment_result=deployment_result, - deployment_status=deployment_status) + deployment_status=deployment_status, + replica_no=replica_no + ) self.db_connection.add(result_info) self.db_connection.commit() return @@ -439,6 +468,7 @@ class FedMLDeploymentResultInfoModel(Base): device_id = Column(TEXT) deployment_result = Column(TEXT) deployment_status = Column(TEXT) + replica_no = Column(TEXT) class FedMLDeploymentRunInfoModel(Base): diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_deployment.py b/python/fedml/computing/scheduler/model_scheduler/device_model_deployment.py index 0a8c3b6ce9..7356724277 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_deployment.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_deployment.py @@ -34,36 +34,15 @@ from .device_http_inference_protocol import FedMLHttpInference +from fedml.computing.scheduler.model_scheduler.device_model_cache import FedMLModelCache no_real_gpu_allocation = None -class CPUUnpickler(pickle.Unpickler): - def find_class(self, module, name): - if module == 'torch.storage' and name == '_load_from_bytes': - return lambda b: torch.load(io.BytesIO(b), map_location='cpu') - else: - return super().find_class(module, name) - - def request_gpu_ids_on_deployment(edge_id, end_point_id, num_gpus=None, master_device_id=None): gpu_ids = None client_device_id = os.getenv("FEDML_CURRENT_EDGE_ID") - try: - ComputeCacheManager.get_instance().set_redis_params() - with ComputeCacheManager.get_instance().lock( - ComputeCacheManager.get_instance().get_gpu_cache().get_device_run_lock_key(edge_id, end_point_id) - ): - if num_gpus is None: - num_gpus = ComputeCacheManager.get_instance().get_gpu_cache().get_device_run_num_gpus(edge_id, end_point_id) - num_gpus = int(num_gpus) if num_gpus is not None and str(num_gpus) != "" else 1 - gpu_ids = ComputeCacheManager.get_instance().get_gpu_cache().get_device_run_gpu_ids(edge_id, end_point_id) - except Exception as e: - logging.info(f"Execption when request gpu ids. {traceback.format_exc()}") - gpu_ids = None - raise e - if gpu_ids is None: cuda_visable_gpu_ids = JobRunnerUtils.get_instance().occupy_gpu_ids( end_point_id, num_gpus, client_device_id, inner_id=end_point_id, @@ -92,36 +71,9 @@ def start_deployment(end_point_id, end_point_name, model_id, model_version, inference_use_gpu, inference_memory_size, inference_convertor_image, inference_server_image, infer_host, model_is_from_open, model_params, - model_from_open, token, master_ip, edge_id, master_device_id=None): + model_from_open, token, master_ip, edge_id, master_device_id=None, replica_rank=0): logging.info("Model deployment is starting...") - use_simulation_test_without_triton = False - model_metadata = {'name': inference_model_name, - 'versions': ['1'], 'platform': 'onnxruntime_onnx', - 'inputs': [{'name': 'input2', 'datatype': 'INT32', 'shape': [1, 24]}, - {'name': 'input1', 'datatype': 'FP32', 'shape': [1, 2]}], - 'outputs': [{'name': 'output', 'datatype': 'FP32', 'shape': [1]}]} - model_config = { - "platform": "onnxruntime", - "max_batch_size": 1, - "input_size": [[1, 24], [1, 2]], - "input_types": ["int", "float"], - "input": [ - { - "name": "input", - "data_type": "TYPE_FP32", - "dims": [] - } - ], - "output": [ - { - "name": "output", - "data_type": "TYPE_FP32", - "dims": [] - } - ] - } - sudo_prefix = "sudo " sys_name = platform.system() if sys_name == "Darwin": @@ -132,194 +84,112 @@ def start_deployment(end_point_id, end_point_name, model_id, model_version, running_model_name = ClientConstants.get_running_model_name( end_point_name, inference_model_name, model_version, end_point_id, model_id, edge_id=edge_id) - # Check whether triton server is running. - triton_server_is_running = False - if not use_simulation_test_without_triton: - triton_server_container_name = "{}".format(ClientConstants.FEDML_TRITON_SERVER_CONTAINER_NAME_PREFIX) - if not ClientConstants.is_running_on_k8s(): - check_triton_server_running_cmds = "{}docker ps |grep {}".format(sudo_prefix, triton_server_container_name) - running_process = ClientConstants.exec_console_with_script(check_triton_server_running_cmds, - should_capture_stdout=True, - should_capture_stderr=True) - ret_code, out, err = ClientConstants.get_console_pipe_out_err_results(running_process) - if out is not None: - out_str = sys_utils.decode_our_err_result(out) - if str(out_str) != "": - triton_server_is_running = True - - # Convert models from pytorch to onnx format if model_is_from_open: - if model_from_open is None: - return running_model_name, "", model_version, {}, {} - - logging.info("model binary file: {}".format(model_bin_file)) - with open(model_bin_file, 'rb') as model_pkl_file: - if not torch.cuda.is_available(): - try: - open_model_params = CPUUnpickler(model_pkl_file).load() - except Exception as ex: - logging.info("load model exceptions when using CPU_Unpickler: {}".format(traceback.format_exc())) - return "", "", model_version, model_metadata, model_config - else: - open_model_params = pickle.load(model_pkl_file) - model_from_open.load_state_dict(open_model_params) - model_from_open.eval() - - if inference_engine == ClientConstants.INFERENCE_ENGINE_TYPE_INT_TRITON: - logging.info("convert the onnx model when the mode is from FedML® Nexus AI Platform..") - logging.info("Input size {}, input types {}".format(model_params["input_size"], - model_params["input_types"])) - input_size = model_params["input_size"] - input_types = model_params["input_types"] - - dummy_input_list = [] - for index, input_i in enumerate(input_size): - if input_types[index] == "int": - this_input = torch.randint(0, 1, input_i).clone().detach() - else: - this_input = torch.zeros(input_i).clone().detach() - dummy_input_list.append(this_input) - - onnx_model_path = os.path.join(model_storage_local_path, - ClientConstants.FEDML_CONVERTED_MODEL_DIR_NAME, - running_model_name, ClientConstants.INFERENCE_MODEL_VERSION) - if not os.path.exists(onnx_model_path): - os.makedirs(onnx_model_path, exist_ok=True) - onnx_model_path = os.path.join(onnx_model_path, "model.onnx") - - convert_model_to_onnx(model_from_open, onnx_model_path, dummy_input_list, input_size) - elif ClientConstants.INFERENCE_ENGINE_TYPE_INT_DEFAULT: # we do not convert the model to onnx in llm - logging.info("LLM model loaded from the open") + logging.error("The model is directly export from open, currently do not convert the model to servable format.") + return "", "", None, None, None + + # Parse the model config file and get the necessary information for the deployment + model_config_path = os.path.join(model_storage_local_path, "fedml_model_config.yaml") + with open(model_config_path, 'r') as file: + config = yaml.safe_load(file) + # Resource related + use_gpu = config.get('use_gpu', False) + in_gpu_ids = config.get('gpu_ids', gpu_ids) + num_gpus = config.get('num_gpus', None) + if not use_gpu: + num_gpus = 0 else: - raise Exception("Unsupported inference engine type: {}".format(inference_engine)) - elif model_is_from_open == False or model_is_from_open is None: - model_location = os.path.join(model_storage_local_path, "fedml_model.bin") - try: - model = torch.jit.load(model_location) - model.eval() - except Exception as e: - logging.info( - "Cannot locate the .bin file, will read it from" - " the fedml_model_config.yaml with the key [local_model_dir] ") - model_config_path = os.path.join(model_storage_local_path, "fedml_model_config.yaml") - with open(model_config_path, 'r') as file: - config = yaml.safe_load(file) - # Resource related - use_gpu = config.get('use_gpu', False) - in_gpu_ids = config.get('gpu_ids', gpu_ids) - num_gpus = config.get('num_gpus', None) - if not use_gpu: - num_gpus = 0 - else: - if num_gpus is None: - num_gpus = len(in_gpu_ids) if in_gpu_ids is not None else 1 - usr_indicated_wait_time = config.get('deploy_timeout', 900) - usr_indicated_worker_port = config.get('worker_port', "") - if usr_indicated_worker_port == "": - usr_indicated_worker_port = os.environ.get("FEDML_WORKER_PORT", "") - shm_size = config.get('shm_size', None) - storage_opt = config.get('storage_opt', None) - tmpfs = config.get('tmpfs', None) - cpus = config.get('cpus', None) - if cpus is not None: - cpus = int(cpus) - memory = config.get('memory', None) - - if usr_indicated_worker_port == "": - usr_indicated_worker_port = None - else: - usr_indicated_worker_port = int(usr_indicated_worker_port) - - worker_port_env = os.environ.get("FEDML_WORKER_PORT", "") - worker_port_from_config = config.get('worker_port', "") - print(f"usr_indicated_worker_port {usr_indicated_worker_port}, worker port env {worker_port_env}, " - f"worker port from config {worker_port_from_config}") - - usr_indicated_retry_cnt = max(int(usr_indicated_wait_time) // 10, 1) - inference_image_name = config.get('inference_image_name', - ClientConstants.INFERENCE_SERVER_CUSTOME_IMAGE) - image_pull_policy = config.get('image_pull_policy', SchedulerConstants.IMAGE_PULL_POLICY_IF_NOT_PRESENT) - - # Source code dir, bootstrap dir, data cache dir - src_code_dir = os.path.join(model_storage_local_path, config.get('source_code_dir', "")) - - # Get the bootstrap and job commands inside the yaml file - bootstrap_cmds_str_frm_yaml = config.get('bootstrap', "") - job_cmds_str_frm_yaml = config.get('job', "") - - if bootstrap_cmds_str_frm_yaml != "" or job_cmds_str_frm_yaml != "": - auto_gen_bootstrap_file_name = "fedml-deploy-bootstrap-entry-auto-gen.sh" - src_bootstrap_file_path = os.path.join(model_storage_local_path, auto_gen_bootstrap_file_name) - with open(src_bootstrap_file_path, 'w') as f: - f.write("cd /home/fedml/models_serving/\n") - f.write(bootstrap_cmds_str_frm_yaml) - f.write("\n") - f.write("cd /home/fedml/models_serving/\n") - f.write(job_cmds_str_frm_yaml) - else: - src_bootstrap_file_path = "" + if num_gpus is None: + num_gpus = len(in_gpu_ids) if in_gpu_ids is not None else 1 + usr_indicated_wait_time = config.get('deploy_timeout', 900) + usr_indicated_worker_port = config.get('worker_port', "") + if usr_indicated_worker_port == "": + usr_indicated_worker_port = os.environ.get("FEDML_WORKER_PORT", "") + shm_size = config.get('shm_size', None) + storage_opt = config.get('storage_opt', None) + tmpfs = config.get('tmpfs', None) + cpus = config.get('cpus', None) + if cpus is not None: + cpus = int(cpus) + memory = config.get('memory', None) + + if usr_indicated_worker_port == "": + usr_indicated_worker_port = None + else: + usr_indicated_worker_port = int(usr_indicated_worker_port) + + worker_port_env = os.environ.get("FEDML_WORKER_PORT", "") + worker_port_from_config = config.get('worker_port', "") + print(f"usr_indicated_worker_port {usr_indicated_worker_port}, worker port env {worker_port_env}, " + f"worker port from config {worker_port_from_config}") + + usr_indicated_retry_cnt = max(int(usr_indicated_wait_time) // 10, 1) + inference_image_name = config.get('inference_image_name', + ClientConstants.INFERENCE_SERVER_CUSTOME_IMAGE) + image_pull_policy = config.get('image_pull_policy', SchedulerConstants.IMAGE_PULL_POLICY_IF_NOT_PRESENT) + + # Source code dir, bootstrap dir, data cache dir + src_code_dir = os.path.join(model_storage_local_path, config.get('source_code_dir', "")) + + # Get the bootstrap and job commands inside the yaml file + bootstrap_cmds_str_frm_yaml = config.get('bootstrap', "") + job_cmds_str_frm_yaml = config.get('job', "") + + if bootstrap_cmds_str_frm_yaml != "" or job_cmds_str_frm_yaml != "": + auto_gen_bootstrap_file_name = "fedml-deploy-bootstrap-entry-auto-gen.sh" + src_bootstrap_file_path = os.path.join(model_storage_local_path, auto_gen_bootstrap_file_name) + with open(src_bootstrap_file_path, 'w') as f: + f.write("cd /home/fedml/models_serving/\n") + f.write(bootstrap_cmds_str_frm_yaml) + f.write("\n") + f.write("cd /home/fedml/models_serving/\n") + f.write(job_cmds_str_frm_yaml) + else: + src_bootstrap_file_path = "" - data_cache_dir_input = config.get('data_cache_dir', "") - request_input_example = config.get('request_input_example', None) - extra_envs = config.get('environment_variables', None) + data_cache_dir_input = config.get('data_cache_dir', "") + request_input_example = config.get('request_input_example', None) + extra_envs = config.get('environment_variables', None) - # Serving dir inside docker - dst_model_serving_dir = "/home/fedml/models_serving" - relative_entry = config.get('entry_point') - if src_bootstrap_file_path != "": - dst_bootstrap_dir = os.path.join(dst_model_serving_dir, auto_gen_bootstrap_file_name) - else: - dst_bootstrap_dir = "" + # Serving dir inside docker + dst_model_serving_dir = "/home/fedml/models_serving" + relative_entry = config.get('entry_point') + if src_bootstrap_file_path != "": + dst_bootstrap_dir = os.path.join(dst_model_serving_dir, auto_gen_bootstrap_file_name) + else: + dst_bootstrap_dir = "" - # If using customized image, then bootstrap + job will be the entry point - enable_custom_image = config.get("enable_custom_image", False) - customized_image_entry_cmd = \ - "/bin/bash /home/fedml/models_serving/fedml-deploy-bootstrap-entry-auto-gen.sh" + # If using customized image, then bootstrap + job will be the entry point + enable_custom_image = config.get("enable_custom_image", False) + customized_image_entry_cmd = \ + "/bin/bash /home/fedml/models_serving/fedml-deploy-bootstrap-entry-auto-gen.sh" - docker_registry_user_name = config.get("docker_registry_user_name", "") - docker_registry_user_password = config.get("docker_registry_user_password", "") - docker_registry = config.get("docker_registry", "") + docker_registry_user_name = config.get("docker_registry_user_name", "") + docker_registry_user_password = config.get("docker_registry_user_password", "") + docker_registry = config.get("docker_registry", "") - port_inside_container = int(config.get("port_inside_container", 2345)) - use_triton = config.get("use_triton", False) - if use_triton: - inference_type = "triton" - else: - inference_type = "default" - - if src_code_dir == "": - raise Exception("Please indicate source_code_dir in the fedml_model_config.yaml") - if relative_entry == "": - logging.warning("You missed main_entry in the fedml_model_config.yaml") - - if num_gpus > 0: - gpu_ids, gpu_attach_cmd = request_gpu_ids_on_deployment( - edge_id, end_point_id, num_gpus=num_gpus, master_device_id=master_device_id) - - if inference_engine == ClientConstants.INFERENCE_ENGINE_TYPE_INT_TRITON: - # configuration passed by user in the Cli - input_size = model_params["input_size"] - input_types = model_params["input_types"] - logging.info("convert the onnx model when the mode is from the general PyTorch...") - logging.info("Input size {}, input types {}".format(model_params["input_size"], - model_params["input_types"])) - dummy_input_list = [] - for index, input_i in enumerate(input_size): - if input_types[index] == "int": - this_input = torch.randint(0, 1, input_i).clone().detach() - else: - this_input = torch.zeros(input_i).clone().detach() - dummy_input_list.append(this_input) + port_inside_container = int(config.get("port_inside_container", 2345)) + use_triton = config.get("use_triton", False) + if use_triton: + inference_type = "triton" + else: + inference_type = "default" + + # Config check + if src_code_dir == "": + raise Exception("Please indicate source_code_dir in the fedml_model_config.yaml") + if relative_entry == "": + logging.warning("You missed main_entry in the fedml_model_config.yaml") - onnx_model_path = os.path.join(model_storage_local_path, - ClientConstants.FEDML_CONVERTED_MODEL_DIR_NAME, - running_model_name, ClientConstants.INFERENCE_MODEL_VERSION) - logging.info("converted onnx model path: {}".format(onnx_model_path)) - if not os.path.exists(onnx_model_path): - os.makedirs(onnx_model_path, exist_ok=True) - onnx_model_path = os.path.join(onnx_model_path, "model.onnx") + # Request the GPU ids for the deployment + if num_gpus > 0: + gpu_ids, gpu_attach_cmd = request_gpu_ids_on_deployment( + edge_id, end_point_id, num_gpus=num_gpus, master_device_id=master_device_id) - convert_model_to_onnx(model, onnx_model_path, dummy_input_list, input_size) + # set replica and their gpu ids + FedMLModelCache.get_instance().set_redis_params() + FedMLModelCache.get_instance().set_replica_gpu_ids( + end_point_id, end_point_name, inference_model_name, edge_id, replica_rank+1, gpu_ids) logging.info("move converted model to serving dir for inference...") model_serving_dir = ClientConstants.get_model_serving_dir() @@ -339,265 +209,198 @@ def start_deployment(end_point_id, end_point_name, model_id, model_version, if not os.path.exists(dst_model_file): shutil.copyfile(src_model_file, dst_model_file) - if inference_engine == ClientConstants.INFERENCE_ENGINE_TYPE_INT_DEFAULT: - logging.info(f"master ip: {master_ip}, worker ip: {infer_host}") - if infer_host == master_ip: - logging.info("infer_host is the same as master ip, will use 127.0.0.1 to avoid firewall issue") - infer_host = "127.0.0.1" + if inference_engine != ClientConstants.INFERENCE_ENGINE_TYPE_INT_DEFAULT: + raise Exception(f"inference engine {inference_engine} is not supported") - try: - client = docker.from_env() - if enable_custom_image and docker_registry_user_name != "" and docker_registry_user_password != "" \ - and docker_registry != "": - client.login(username=docker_registry_user_name, password=docker_registry_user_password, - registry=docker_registry) - except Exception: - logging.error("Failed to connect to the docker daemon, please ensure that you have " - "installed Docker Desktop or Docker Engine, and the docker is running") - return "", "", None, None, None - - container_prefix = "{}".format(ClientConstants.FEDML_DEFAULT_SERVER_CONTAINER_NAME_PREFIX) + "__" + \ - security_utils.get_content_hash(running_model_name) - - same_model_container_rank = ContainerUtils.get_container_rank_same_model(container_prefix) - if same_model_container_rank == -1: - logging.error(f"Fail to get existed docker with {end_point_name} {inference_model_name}") - raise Exception("Failed to get the container rank") - default_server_container_name = container_prefix + "__" + str(same_model_container_rank) + # Get the master device id + logging.info(f"master ip: {master_ip}, worker ip: {infer_host}") + if infer_host == master_ip: + logging.info("infer_host is the same as master ip, will use 127.0.0.1 to avoid firewall issue") + infer_host = "127.0.0.1" - try: - exist_container_obj = client.containers.get(default_server_container_name) - except docker.errors.NotFound: - exist_container_obj = None - except docker.errors.APIError: - raise Exception("Failed to get the container object") - - if exist_container_obj is not None: - client.api.remove_container(exist_container_obj.id, v=True, force=True) - device_requests = [] - if no_real_gpu_allocation is not None: - use_gpu = not no_real_gpu_allocation - if use_gpu: - logging.info("Number of GPUs: {}".format(num_gpus)) - if gpu_ids is not None: - gpu_id_list = map(lambda x: str(x), gpu_ids) - device_requests.append( - docker.types.DeviceRequest(device_ids=list(gpu_id_list), capabilities=[['gpu']])) + try: + client = docker.from_env() + if enable_custom_image and docker_registry_user_name != "" and docker_registry_user_password != "" \ + and docker_registry != "": + client.login(username=docker_registry_user_name, password=docker_registry_user_password, + registry=docker_registry) + except Exception: + logging.error("Failed to connect to the docker daemon, please ensure that you have " + "installed Docker Desktop or Docker Engine, and the docker is running") + return "", "", None, None, None + + container_prefix = ("{}".format(ClientConstants.FEDML_DEFAULT_SERVER_CONTAINER_NAME_PREFIX) + "__" + + security_utils.get_content_hash(running_model_name)) + + default_server_container_name = container_prefix + "__" + str(replica_rank) + + try: + exist_container_obj = client.containers.get(default_server_container_name) + except docker.errors.NotFound: + exist_container_obj = None + except docker.errors.APIError: + raise Exception("Failed to get the container object") + + # Allocate the GPU + # TODO: Make sure no competition for each replica in a single deployment + if exist_container_obj is not None: + client.api.remove_container(exist_container_obj.id, v=True, force=True) + device_requests = [] + if no_real_gpu_allocation is not None: + use_gpu = not no_real_gpu_allocation + if use_gpu: + logging.info("Number of GPUs: {}".format(num_gpus)) + if gpu_ids is not None: + gpu_id_list = map(lambda x: str(x), gpu_ids) + device_requests.append( + docker.types.DeviceRequest(device_ids=list(gpu_id_list), capabilities=[['gpu']])) + else: + device_requests.append( + docker.types.DeviceRequest(count=num_gpus, capabilities=[['gpu']])) + logging.info(f"device_requests: {device_requests}") + + # Pull the inference image + logging.info(f"Start pulling the inference image {inference_image_name}..., may take a few minutes...") + ContainerUtils.get_instance().pull_image_with_policy(image_pull_policy, inference_image_name) + + logging.info("Start creating the inference container...") + volumns = [] + binds = {} + environment = {} + + # data_cache_dir mounting + assert type(data_cache_dir_input) == dict or type(data_cache_dir_input) == str + if type(data_cache_dir_input) == str: + # In this case, we mount to the same folder, if has ~, we replace it with /home/fedml + src_data_cache_dir, dst_data_cache_dir = "", "" + if data_cache_dir_input != "": + if data_cache_dir_input[0] == "~": + src_data_cache_dir = os.path.expanduser(data_cache_dir_input) + dst_data_cache_dir = data_cache_dir_input.replace("~", "/home/fedml") else: - device_requests.append( - docker.types.DeviceRequest(count=num_gpus, capabilities=[['gpu']])) - logging.info(f"device_requests: {device_requests}") - logging.info(f"Start pulling the inference image {inference_image_name}..., may take a few minutes...") - - ContainerUtils.get_instance().pull_image_with_policy(image_pull_policy, inference_image_name) - - logging.info("Start creating the inference container...") - volumns = [] - binds = {} - environment = {} - - assert type(data_cache_dir_input) == dict or type(data_cache_dir_input) == str - if type(data_cache_dir_input) == str: - # In this case, we mount to the same folder, if has ~, we replace it with /home/fedml - src_data_cache_dir, dst_data_cache_dir = "", "" - if data_cache_dir_input != "": - if data_cache_dir_input[0] == "~": - src_data_cache_dir = os.path.expanduser(data_cache_dir_input) - dst_data_cache_dir = data_cache_dir_input.replace("~", "/home/fedml") + # check if the data_cache_dir is a relative path + if data_cache_dir_input[0] != "/": + raise "data_cache_dir_input has to be an absolute path or start with ~" else: - # check if the data_cache_dir is a relative path - if data_cache_dir_input[0] != "/": - raise "data_cache_dir_input has to be an absolute path or start with ~" - else: - src_data_cache_dir = data_cache_dir_input - dst_data_cache_dir = data_cache_dir_input - logging.info(f"src_data_cache_dir: {src_data_cache_dir}, dst_data_cache_dir: {dst_data_cache_dir}") - - if type(src_data_cache_dir) == str and src_data_cache_dir != "": - logging.info("Start copying the data cache to the container...") - if os.path.exists(src_data_cache_dir): - volumns.append(src_data_cache_dir) - binds[src_data_cache_dir] = { - "bind": dst_data_cache_dir, - "mode": "rw" - } - environment["DATA_CACHE_FOLDER"] = dst_data_cache_dir - else: - for k, v in data_cache_dir_input.items(): - if os.path.exists(k): - volumns.append(v) - binds[k] = { - "bind": v, + src_data_cache_dir = data_cache_dir_input + dst_data_cache_dir = data_cache_dir_input + logging.info(f"src_data_cache_dir: {src_data_cache_dir}, dst_data_cache_dir: {dst_data_cache_dir}") + + if type(src_data_cache_dir) == str and src_data_cache_dir != "": + logging.info("Start copying the data cache to the container...") + if os.path.exists(src_data_cache_dir): + volumns.append(src_data_cache_dir) + binds[src_data_cache_dir] = { + "bind": dst_data_cache_dir, "mode": "rw" } - else: - logging.warning(f"{k} does not exist, skip mounting it to the container") - logging.info(f"Data cache mount: {volumns}, {binds}") - - # Default - if not enable_custom_image or (enable_custom_image and relative_entry != ""): - logging.info("Start copying the source code to the container...") - volumns.append(src_code_dir) - binds[src_code_dir] = { - "bind": dst_model_serving_dir, - "mode": "rw" - } - environment["MAIN_ENTRY"] = relative_entry - - if not enable_custom_image: - # For some image, the default user is root. Unified to fedml. - environment["HOME"] = "/home/fedml" - environment["BOOTSTRAP_DIR"] = dst_bootstrap_dir - environment["FEDML_CURRENT_RUN_ID"] = end_point_id - environment["FEDML_CURRENT_EDGE_ID"] = edge_id - environment["FEDML_CURRENT_VERSION"] = fedml.get_env_version() - environment["FEDML_ENV_VERSION"] = fedml.get_env_version() - environment["FEDML_ENV_LOCAL_ON_PREMISE_PLATFORM_HOST"] = fedml.get_local_on_premise_platform_host() - environment["FEDML_ENV_LOCAL_ON_PREMISE_PLATFORM_PORT"] = fedml.get_local_on_premise_platform_port() - logging.info(f"volume: {volumns}, binds: {binds}, environment: {environment}") - logging.info(f"dst_model_serving_dir: {dst_model_serving_dir}") - logging.info(f"relative_entry: {relative_entry}") - logging.info(f"src_bootstrap_file_path: {src_bootstrap_file_path}") - logging.info(f"dst_bootstrap_dir: {dst_bootstrap_dir}") - logging.info(f"src_code_dir: {src_code_dir}") - logging.info(f"model_serving_dir: {model_serving_dir}") - - if extra_envs is not None: - for key in extra_envs: - environment[key] = extra_envs[key] - - try: - new_container = client.api.create_container( - image=inference_image_name, - name=default_server_container_name, - volumes=volumns, - ports=[port_inside_container], # port open inside the container - environment=environment, - host_config=client.api.create_host_config( - binds=binds, - port_bindings={ - port_inside_container: usr_indicated_worker_port # Could be either None or a port number - }, - device_requests=device_requests, - shm_size=shm_size, - storage_opt=storage_opt, - tmpfs=tmpfs, - cpu_count=cpus, - mem_limit=memory, - ), - detach=True, - command=customized_image_entry_cmd if enable_custom_image else None - ) - client.api.start(container=new_container.get("Id")) - except Exception as e: - logging.error(f"Failed to create the container with exception {e}, traceback : {traceback.format_exc()}") - - # Get the port allocation - cnt = 0 - while True: - cnt += 1 - try: - if usr_indicated_worker_port is not None: - inference_http_port = usr_indicated_worker_port - break - else: - # Find the random port - port_info = client.api.port(new_container.get("Id"), port_inside_container) - inference_http_port = port_info[0]["HostPort"] - logging.info("inference_http_port: {}".format(inference_http_port)) - break - except: - if cnt >= 5: - raise Exception("Failed to get the port allocation") - time.sleep(3) - - # Logging the info from the container - log_deployment_result(end_point_id, model_id, default_server_container_name, - ClientConstants.CMD_TYPE_RUN_DEFAULT_SERVER, - inference_model_name, inference_engine, inference_http_port, inference_type, - retry_interval=10, deploy_attempt_threshold=usr_indicated_retry_cnt, - request_input_example=request_input_example, infer_host=infer_host, - enable_custom_image=enable_custom_image) - - # Check if the inference server is ready - inference_output_url, running_model_version, ret_model_metadata, ret_model_config = \ - get_model_info(inference_model_name, inference_engine, inference_http_port, - infer_host, False, inference_type, request_input_example=request_input_example, - enable_custom_image=enable_custom_image) - - if inference_output_url == "": - return running_model_name, "", None, None, None - - # testing the inference container - test_input = ret_model_metadata["inputs"] - - # try: - # inference_response = run_http_inference_with_curl_request(inference_output_url, test_input, [], - # inference_type="default") - # logging.info(f"Tested the inference backend with {test_input}, the response is {inference_response}") - # except Exception as e: - # logging.info("Tested the inference backend, exceptions occurred: {}".format(traceback.format_exc())) - # inference_output_url = "" - - model_metadata = ret_model_metadata - logging.info(model_metadata) - elif inference_engine == ClientConstants.INFERENCE_ENGINE_TYPE_INT_TRITON: - logging.info("prepare to run triton server...") - if not use_simulation_test_without_triton: - if not triton_server_is_running and not ClientConstants.is_running_on_k8s(): - triton_server_cmd = "{}docker stop {}; {}docker rm {}; {}docker run --name {} {} -p{}:8000 " \ - "-p{}:8001 -p{}:8002 " \ - "--shm-size {} " \ - "-v {}:/models {} " \ - "bash -c \"pip install transformers && tritonserver --strict-model-config=false " \ - "--model-control-mode=poll --repository-poll-secs={} " \ - "--model-repository=/models\" ".format(sudo_prefix, triton_server_container_name, - sudo_prefix, triton_server_container_name, - sudo_prefix, triton_server_container_name, - gpu_attach_cmd, - inference_http_port, - inference_grpc_port, - inference_metric_port, - inference_memory_size, - model_serving_dir, - inference_server_image, - ClientConstants.FEDML_MODEL_SERVING_REPO_SCAN_INTERVAL) - logging.info("Run triton inference server: {}".format(triton_server_cmd)) - triton_server_process = ClientConstants.exec_console_with_script(triton_server_cmd, - should_capture_stdout=False, - should_capture_stderr=False, - no_sys_out_err=True) - log_deployment_result(end_point_id, model_id, triton_server_container_name, - ClientConstants.CMD_TYPE_RUN_TRITON_SERVER, triton_server_process.pid, - running_model_name, inference_engine, inference_http_port) - - inference_output_url, running_model_version, ret_model_metadata, ret_model_config = \ - get_model_info(running_model_name, inference_engine, inference_http_port, infer_host) - if inference_output_url != "": - # Send the test request to the inference backend and check if the response is normal - input_json, output_json = build_inference_req(end_point_name, inference_model_name, - token, ret_model_metadata) - try: - inference_response = run_http_inference_with_curl_request(inference_output_url, - input_json["inputs"], - input_json["outputs"]) - logging.info("Tested the inference backend, the response is {}".format(inference_response)) - except Exception as e: - logging.info("Tested the inference backend, exceptions occurred: {}".format(traceback.format_exc())) - inference_output_url = "" - - if inference_output_url != "": - logging.info( - "Deploy model successfully, inference url: {}, model metadata: {}, model config: {}".format( - inference_output_url, model_metadata, model_config)) - model_metadata = ret_model_metadata - model_config = ret_model_config - else: - inference_output_url = f"http://localhost:{inference_http_port}/v2/models/{running_model_name}/versions/1/infer" + environment["DATA_CACHE_FOLDER"] = dst_data_cache_dir else: - raise Exception("inference engine {} is not supported".format(inference_engine)) + for k, v in data_cache_dir_input.items(): + if os.path.exists(k): + volumns.append(v) + binds[k] = { + "bind": v, + "mode": "rw" + } + else: + logging.warning(f"{k} does not exist, skip mounting it to the container") + logging.info(f"Data cache mount: {volumns}, {binds}") + + # Default mounting + if not enable_custom_image or (enable_custom_image and relative_entry != ""): + logging.info("Start copying the source code to the container...") + volumns.append(src_code_dir) + binds[src_code_dir] = { + "bind": dst_model_serving_dir, + "mode": "rw" + } + environment["MAIN_ENTRY"] = relative_entry + + # Environment variables + if not enable_custom_image: + # For some image, the default user is root. Unified to fedml. + environment["HOME"] = "/home/fedml" + + environment["BOOTSTRAP_DIR"] = dst_bootstrap_dir + environment["FEDML_CURRENT_RUN_ID"] = end_point_id + environment["FEDML_CURRENT_EDGE_ID"] = edge_id + environment["FEDML_CURRENT_VERSION"] = fedml.get_env_version() + environment["FEDML_ENV_VERSION"] = fedml.get_env_version() + environment["FEDML_ENV_LOCAL_ON_PREMISE_PLATFORM_HOST"] = fedml.get_local_on_premise_platform_host() + environment["FEDML_ENV_LOCAL_ON_PREMISE_PLATFORM_PORT"] = fedml.get_local_on_premise_platform_port() + + if extra_envs is not None: + for key in extra_envs: + environment[key] = extra_envs[key] + + try: + new_container = client.api.create_container( + image=inference_image_name, + name=default_server_container_name, + volumes=volumns, + ports=[port_inside_container], # port open inside the container + environment=environment, + host_config=client.api.create_host_config( + binds=binds, + port_bindings={ + port_inside_container: usr_indicated_worker_port # Could be either None or a port number + }, + device_requests=device_requests, + shm_size=shm_size, + storage_opt=storage_opt, + tmpfs=tmpfs, + cpu_count=cpus, + mem_limit=memory, + ), + detach=True, + command=customized_image_entry_cmd if enable_custom_image else None + ) + client.api.start(container=new_container.get("Id")) + except Exception as e: + logging.error(f"Failed to create the container with exception {e}, traceback : {traceback.format_exc()}") + return "", "", None, None, None - return running_model_name, inference_output_url, model_version, model_metadata, model_config + # Get the port allocation + cnt = 0 + while True: + cnt += 1 + try: + if usr_indicated_worker_port is not None: + inference_http_port = usr_indicated_worker_port + break + else: + # Find the random port + port_info = client.api.port(new_container.get("Id"), port_inside_container) + inference_http_port = port_info[0]["HostPort"] + logging.info("inference_http_port: {}".format(inference_http_port)) + break + except: + if cnt >= 5: + raise Exception("Failed to get the port allocation") + time.sleep(3) + + # Logging the info from the container + log_deployment_result(end_point_id, model_id, default_server_container_name, + ClientConstants.CMD_TYPE_RUN_DEFAULT_SERVER, + inference_model_name, inference_engine, inference_http_port, inference_type, + retry_interval=10, deploy_attempt_threshold=usr_indicated_retry_cnt, + request_input_example=request_input_example, infer_host=infer_host, + enable_custom_image=enable_custom_image) + + # Check if the inference server is ready + inference_output_url, running_model_version, ret_model_metadata, ret_model_config = \ + get_model_info(inference_model_name, inference_engine, inference_http_port, + infer_host, False, inference_type, request_input_example=request_input_example, + enable_custom_image=enable_custom_image) + + if inference_output_url == "": + return running_model_name, "", None, None, None + + model_metadata = ret_model_metadata + logging.info(model_metadata) + + return running_model_name, inference_output_url, model_version, model_metadata, ret_model_config def build_inference_req(end_point_name, model_name, token, in_model_metadata): diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_inference.py b/python/fedml/computing/scheduler/model_scheduler/device_model_inference.py index 6e99851d73..3787e35b80 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_inference.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_inference.py @@ -26,34 +26,34 @@ pass -class Settings(BaseSettings): - redis_addr: str - redis_port: str - redis_password: str - end_point_name: str - model_name: str - model_version: str - model_infer_url: str - version: str - use_mqtt_inference: bool - use_worker_gateway: bool - ext_info: str - - -settings = Settings() - -# class settings: -# redis_addr = "127.0.0.1" -# redis_port = 6379 -# redis_password = "fedml_default" -# end_point_name = "" -# model_name = "" -# model_version = "" -# model_infer_url = "127.0.0.1" -# version = "dev" -# use_mqtt_inference = False -# use_worker_gateway = False -# ext_info = "2b34303961245c4f175f2236282d7a272c040b0904747579087f6a760112030109010c215d54505707140005190a051c347f365c4a430c020a7d39120e26032a78730f797f7c031f0901657e75" +# class Settings(BaseSettings): +# redis_addr: str +# redis_port: str +# redis_password: str +# end_point_name: str +# model_name: str +# model_version: str +# model_infer_url: str +# version: str +# use_mqtt_inference: bool +# use_worker_gateway: bool +# ext_info: str +# +# +# settings = Settings() + +class settings: + redis_addr = "127.0.0.1" + redis_port = 6379 + redis_password = "fedml_default" + end_point_name = "" + model_name = "" + model_version = "" + model_infer_url = "127.0.0.1" + version = "dev" + use_mqtt_inference = False + use_worker_gateway = False + ext_info = "2b34303961245c4f175f2236282d7a272c040b0904747579087f6a760112030109010c215d54505707140005190a051c347f365c4a430c020a7d39120e26032a78730f797f7c031f0901657e75" api = FastAPI() @@ -224,12 +224,17 @@ def retrieve_info_by_endpoint_id(end_point_id, in_end_point_name=None, in_model_ redis_key = FedMLModelCache.get_instance(settings.redis_addr, settings.redis_port). \ get_end_point_full_key_by_id(end_point_id) if redis_key is not None: + end_point_name = "" + model_name = "" if in_end_point_name is not None: end_point_name = in_end_point_name model_name = redis_key[len(f"{FedMLModelCache.FEDML_MODEL_DEPLOYMENT_STATUS_TAG}-{end_point_id}-{in_end_point_name}-"):] else: # e.g. FEDML_MODEL_DEPLOYMENT_STATUS--1234-dummy_endpoint_name-dummy_model_name - end_point_id, end_point_name, model_name = redis_key.split("--")[1].split("-") + try: + end_point_id, end_point_name, model_name = redis_key.split("--")[1].split("-") + except Exception as e: + logging.warning(f"Failed to parse redis_key: {redis_key}. Could not retrieve only use end_point_id.") if enable_check: if end_point_name != in_end_point_name or model_name != in_model_name: @@ -352,6 +357,6 @@ def logging_inference_request(request, response): if __name__ == "__main__": import uvicorn - port = 2204 + port = 2203 logging.basicConfig(level=logging.INFO) uvicorn.run(api, host="0.0.0.0", port=port, log_level="info") diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_msg_object.py b/python/fedml/computing/scheduler/model_scheduler/device_model_msg_object.py index 062b591853..a6c6244108 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_msg_object.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_msg_object.py @@ -1,5 +1,5 @@ - import json +import logging class FedMLModelMsgObject(object): @@ -37,7 +37,10 @@ def __init__(self, topic, payload): }""" # get deployment params - request_json = json.loads(payload) + if isinstance(payload, dict): + request_json = payload + else: + request_json = json.loads(payload) self.msg_topic = topic self.request_json = request_json self.run_id = request_json["end_point_id"] @@ -58,13 +61,54 @@ def __init__(self, topic, payload): self.inference_engine = self.model_config.get("inference_engine", 0) self.inference_end_point_id = self.run_id - self. request_json["run_id"] = self.run_id + self.request_json["run_id"] = self.run_id + + self.gpu_topology = self.get_devices_avail_gpus() + self.gpu_per_replica = self.get_gpu_per_replica() + + self.max_unavailable_rate = self.model_config.get("max_unavailable_rate", 0.1) + + def get_devices_avail_gpus(self): + """ + { + "gpu_topology": {"id1": 1, "id2": 1} # Here the 1 means gpu card, not replica + } + """ + # [Test1] using self.request_json["parameters"]["gpu_topology"] + # logging.info(f"[Replica Controller] [endpoint {self.run_id} ] devices_avail_gpus:" + # f" {self.request_json['parameters']['gpu_topology']}") + # res = self.request_json["parameters"]["gpu_topology"] + + # [Test2] Using self.scale_min + # res = {} + # for id in self.request_json["device_ids"]: + # if str(id) == str(self.device_ids[0]): + # continue + # res[id] = int(self.scale_min) + # return res + + # [Prod] Using self.request_json["gpu_topology"] + if "gpu_topology" not in self.request_json: + logging.warning("gpu_topology not found in request_json, using scale_min instead") + res = {} + for id in self.request_json["device_ids"]: + if str(id) == str(self.device_ids[0]): + continue + res[id] = int(self.scale_min) + return res + + logging.info(f"[Replica Controller] [endpoint {self.run_id}] " + f"devices_avail_gpus: {self.request_json['gpu_topology']}") + + return self.request_json["gpu_topology"] + + def get_gpu_per_replica(self): + """ + Read gpu_per_replica from user's config yaml file. Default 1. + """ + if "parameters" in self.request_json and "gpu_per_replica" in self.request_json["parameters"]: + return self.request_json["parameters"]["gpu_per_replica"] + return 1 def show(self, prefix=""): - print("{}end point id: {}, model name: {}, model id: {}," - " model version: {}, model url: {}".format(prefix, - self.inference_end_point_id, - self.model_name, - self.id, - self.model_version, - self.model_url)) + logging.info(f"{prefix} [FedMLModelMsgObject] [run_id {self.run_id}] [end_point_name {self.end_point_name}]") diff --git a/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py b/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py new file mode 100644 index 0000000000..261da73028 --- /dev/null +++ b/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py @@ -0,0 +1,414 @@ +import logging +import copy +from .device_model_cache import FedMLModelCache +from .device_model_msg_object import FedMLModelMsgObject +from .device_client_constants import ClientConstants + + +class FedMLDeviceReplicaController: + def __init__(self, master_id, request_json: dict): + """ + For each deployment, we have: + master_id: unique id for the master device + e_id: unique id (i.e. endpoint_id) for each deployment + devices_avail_gpus = {device_id1: gpu_num, device_id2: gpu_num, ...} + request_json: json from MLOps for this deployment + total_gpu_num: total number of gpus will be used for this deployment + gpu_per_replica: number of gpus required per replica + min_replica_num: minimum number of replicas required + max_replica_num: maximum number of replicas required + endpoint_name: endpoint name + model_name: model name + target_replica_num: target replica number for each device + target_replica_version: target replica version + curr_replica_num: current replica number for each device + intermediate_replica_num: intermediate replica number for each device + total_replica_version_diff_num: total replica version difference number + max_unavailable_rate: maximum unavailable rate + curr_replica_updating_window: current replica updating window + curr_replica_version: current replica version for each device + intermediate_replica_version: intermediate replica version for each device + """ + self.master_id = master_id + self.request_json = request_json + self.request_msg_obj = FedMLModelMsgObject("replica_controller", request_json) + + self.e_id = self.request_msg_obj.run_id + self.devices_avail_gpus = self.request_msg_obj.gpu_topology + self.total_gpu_num = self.calc_total_gpu_num() + self.gpu_per_replica = self.request_msg_obj.gpu_per_replica + self.min_replica_num = self.request_msg_obj.scale_min + self.max_replica_num = self.request_msg_obj.scale_max + self.endpoint_name = self.request_msg_obj.end_point_name + self.model_name = self.request_msg_obj.model_name + + self.target_replica_num = self.init_id_replica_num() + + self.curr_replica_num = self.get_curr_replica_num_state_frm_db() + self.intermediate_replica_num = copy.deepcopy(self.curr_replica_num) + + # Version control + self.target_replica_version = self.request_msg_obj.model_version + self.max_unavailable_rate = self.request_msg_obj.max_unavailable_rate + self.curr_replica_updating_window = {} + + self.curr_replica_version = self.get_curr_replica_version_frm_db() + self.intermediate_replica_version = copy.deepcopy(self.curr_replica_version) + + self.total_replica_version_diff_num, self.total_replica_version_diff = self.diff_target_curr_replica_version() + + def calc_total_gpu_num(self): + total_gpu_num = 0 + for device_id, gpu_num in self.devices_avail_gpus.items(): + total_gpu_num += gpu_num + return total_gpu_num + + def init_id_replica_num(self): + """ + Initialize the target replica number for each device. + id_replica_num[id] = avail_num // self.gpu_per_replica + """ + id_replica_num = {} + for id, avail_num in self.devices_avail_gpus.items(): + if avail_num % self.gpu_per_replica != 0: + raise ValueError("The number of gpus for each device should be divisible by gpu_per_replica") + id_replica_num[str(id)] = avail_num // self.gpu_per_replica + return id_replica_num + + def diff_target_curr_replica_num(self): + logging.info(f"[Replica Controller] [endpoint {self.e_id} ]target_replica_state: {self.target_replica_num}") + logging.info(f"[Replica Controller] [endpoint {self.e_id} ]curr_replica_state: {self.curr_replica_num}") + diff = self.diff_target_curr_replica_num_impl(self.target_replica_num, self.curr_replica_num) + logging.info( + f"[Replica Controller] [endpoint {self.e_id} ]diff_target_curr_replica_num: {diff}") + return diff + + def diff_target_curr_replica_version(self): + logging.info(f"[Replica Controller] [endpoint {self.e_id} ]" + f"target_replica_version: {self.target_replica_version}") + logging.info(f"[Replica Controller] [endpoint {self.e_id} ]" + f"curr_replica_version: {self.curr_replica_version}") + + num_diff, diff = self.diff_target_curr_replica_version_impl( + self.target_replica_version, self.curr_replica_version) + + logging.info( + f"[Replica Controller] [endpoint {self.e_id} ]diff_target_curr_replica_version: {diff}") + return num_diff, diff + + @staticmethod + def diff_target_curr_replica_num_impl(target_replica_state, curr_replica_state): + """ + Return the difference between target and current replica number. + "op" could only be "add" or "remove". + e.g. + curr_replica_state = {id1: 1, id2: 1} + target_replica_state = {id1: 2, id2: 2} + + return {id1: {"op": "add", "curr_num": 1, "target_num": 2}, id2: {"op": "add", "curr_num": 1, "target_num": 2}} + """ + diff_target_curr_replica_num = {} + assert target_replica_state is not None + + if curr_replica_state is None: + curr_replica_state = {} + for id, target_num in target_replica_state.items(): + diff_target_curr_replica_num[id] = {"op": "add", "curr_num": 0, "target_num": target_num} + return diff_target_curr_replica_num + + for id, target_num in target_replica_state.items(): + if target_num > curr_replica_state[id]: + diff_target_curr_replica_num[id] = {"op": "add", "curr_num": curr_replica_state[id], + "target_num": target_num} + elif target_num < curr_replica_state[id]: + diff_target_curr_replica_num[id] = {"op": "remove", "curr_num": curr_replica_state[id], + "target_num": target_num} + else: + pass + + for id, curr_num in curr_replica_state.items(): + if id not in target_replica_state: + diff_target_curr_replica_num[id] = {"op": "remove", "num": curr_num} + + return diff_target_curr_replica_num + + @staticmethod + def diff_target_curr_replica_version_impl(target_replica_version: str, curr_replica_version): + """ + Return the number of difference, and difference between target and current replica version. + "op" could only be "update". + e.g. + curr_replica_version = { + "id1": {$replica_no: "v1", $replica_no: "v1"}, + "id2": {$replica_no: "v1", $replica_no: "v1"}, + } + target_replica_version = "v2" # Could be different for each device in the future. + + return { + "id1": { + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"}, + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"} + }, + "id2": { + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"}, + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"} + } + } + + Return None if curr_replica_version is None.(i.e. this model has not been deployed yet.) + """ + if curr_replica_version is None: + return 0, None + + diff_target_curr_replica_version = {} + num_diff = 0 + for device_id, device_replicas_version in curr_replica_version.items(): + diff_target_curr_replica_version[device_id] = {} + for replica_no, curr_version in device_replicas_version.items(): + if curr_version != target_replica_version: + num_diff += 1 + diff_target_curr_replica_version[device_id][replica_no] = { + "op": "update", + "new_version": target_replica_version, + "old_version": curr_version + } + if num_diff == 0: + return 0, None + + return num_diff, diff_target_curr_replica_version + + def get_curr_replica_num_state_frm_db(self): + """ + Sync the current replica number state from the database. + Return the current replica number state. + """ + res_frm_db = FedMLModelCache.get_instance().get_deployment_result_list( + self.e_id, self.endpoint_name, self.model_name) + + curr_state = {} + if res_frm_db is None or len(res_frm_db) == 0: + # First time to get the replica number from the database + for id, target_num in self.target_replica_num.items(): + curr_state[str(id)] = 0 + else: + for result_item in res_frm_db: + # Unpack the result_item + result_device_id, _, result_payload = FedMLModelCache.get_instance().get_result_item_info(result_item) + curr_state[str(result_device_id)] = curr_state.get(str(result_device_id), 0) + 1 + return curr_state + + def get_curr_replica_version_frm_db(self): + """ + Sync the current replica version from the database. + Return the current replica version. + { + "id1": {$replica_no: "v1", $replica_no: "v2"}, + "id2": {$replica_no: "v1", $replica_no: "v2"}, + } + Return None if this model has not been deployed yet. + """ + curr_versions = {} + res_frm_db = FedMLModelCache.get_instance().get_deployment_result_list( + self.e_id, self.endpoint_name, self.model_name) + if res_frm_db is None or len(res_frm_db) == 0: + return None + else: + for result_item in res_frm_db: + # Unpack the result_item + result_device_id, replica_no, result_payload = (FedMLModelCache.get_instance(). + get_result_item_info(result_item)) + if str(result_device_id) not in curr_versions: + curr_versions[str(result_device_id)] = {} + curr_versions[str(result_device_id)][str(replica_no)] = result_payload["model_version"] + + return curr_versions + + def generate_diff_to_request_json(self): + """ + Write the diff (curr <> target) to the self.request_json. e.g. + { + "replica_num_diff": { + id1: {"op": "add", "curr_num": 1, "target_num": 2}, + id2: {"op": "add", "curr_num": 1, "target_num": 2}, + id3: {"op": "remove", "curr_num": 1, "target_num": 0} + }, + "replica_version_diff": { + { + "id1": { + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"}, + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"} + }, + "id2": { + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"}, + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"} + } + } + "gpus_per_replica": 1, + } + """ + replica_num_diff_key = "replica_num_diff" + gpu_per_replica_key = "gpus_per_replica" + + replica_num_diff = self.diff_target_curr_replica_num() + self.request_json[replica_num_diff_key] = replica_num_diff + + self.request_json[gpu_per_replica_key] = self.gpu_per_replica + return self.request_json + + def callback_update_curr_replica_num_state(self, changed_device_id, replica_no, op_type): + """ + Callback function to update the current replica number. + curr_state: {id1: 1, id2: 1} + target_replica_state = {id1: 2, id2: 2} + intermediate_state = {id1: 2, id2: 1} + op_type: "add" or "remove" + """ + if (str(changed_device_id) in self.curr_replica_updating_window) and \ + (str(replica_no) in self.curr_replica_updating_window[str(changed_device_id)]): + # Should be viewed as updated, replica number will not be changed. + return + + if str(changed_device_id) not in self.intermediate_replica_num: + raise ValueError(f"changed_device_id {changed_device_id} is not in intermediate_replica_num") + + if op_type == ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED: + self.intermediate_replica_num[str(changed_device_id)] += 1 + elif op_type == ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DELETED: + self.intermediate_replica_num[str(changed_device_id)] -= 1 + + def is_all_replica_num_reconciled(self): + """ + Check if all the replicas are ready. Including the number and version. + """ + for id, replica_no in self.intermediate_replica_num.items(): + if replica_no != self.target_replica_num[id]: + return False + return True + + def get_first_chunk_devices_replica_update(self): + """ + Scroll update. + Set the schema request json, which, will trans to subprocess (device_server_runner). + The subprocess will send the init deployment msg to the worker device(s), + then, the callback_deployment_result will handle the rest updating msg. + + e.g. + { + "replica_version_diff": { + "id1": { + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"}, + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"} + }, + "id2": { + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"}, + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"} + } + }, + } + + Return None if there is no replica version difference. + """ + if self.total_replica_version_diff_num == 0: + return None + + window_size = max(1, int(self.total_replica_version_diff_num * self.max_unavailable_rate)) + + first_chunk_devices_update = {} + + for device_id, device_replicas_version in self.total_replica_version_diff.items(): + for replica_no, diff in device_replicas_version.items(): + if len(first_chunk_devices_update) >= window_size: + break + if device_id not in first_chunk_devices_update: + first_chunk_devices_update[device_id] = {} + first_chunk_devices_update[device_id][replica_no] = diff + + return first_chunk_devices_update + + def init_update_updating_window(self, first_chunk_devices_update): + """ + Initialize the current replica updating window. + """ + self.curr_replica_updating_window = copy.deepcopy(first_chunk_devices_update) + + def callback_update_updating_window(self, device_id, replica_no): + """ + Update the current replica updating window. + """ + if str(device_id) not in self.curr_replica_updating_window: + return + + if str(replica_no) not in self.curr_replica_updating_window[str(device_id)]: + return + + # Remove the replica_no from the updating window + del self.curr_replica_updating_window[str(device_id)][str(replica_no)] + + if len(self.curr_replica_updating_window[str(device_id)]) == 0: + del self.curr_replica_updating_window[str(device_id)] + + # Change this replica's state in the global map + self.intermediate_replica_version[str(device_id)][str(replica_no)] = self.target_replica_version + + def get_next_chunk_devices_replica(self): + """ + If no need for updating, return None + If the intermediate equal to target, return None + If the current updating window is not empty, return None + else, determine the next window, and send the request msg to the device -> replica handler. + """ + if self.total_replica_version_diff_num == 0: + return None + + if self.is_all_replica_version_reconciled(): + return None + + if len(self.curr_replica_updating_window) > 0: + return None + + # Determine the next window + window_size = max(1, int(self.total_replica_version_diff_num * self.max_unavailable_rate)) + + next_chunk_devices_replicas_update = {} + + for id, device_replicas_version in self.intermediate_replica_version.items(): + for replica_no, version in device_replicas_version.items(): + if version != self.target_replica_version: + if id not in next_chunk_devices_replicas_update: + next_chunk_devices_replicas_update[id] = {} + next_chunk_devices_replicas_update[id][replica_no] = { + "op": "update", + "new_version": self.target_replica_version, + "old_version": version + } + if len(next_chunk_devices_replicas_update) >= window_size: + break + + return next_chunk_devices_replicas_update + + def is_all_replica_version_reconciled(self): + """ + Check if all the replicas are ready. Including the number and version. + """ + if self.total_replica_version_diff_num == 0: + return True + + for id, device_replicas_version in self.intermediate_replica_version.items(): + for replica_no, version in device_replicas_version.items(): + if version != self.target_replica_version: + return False + return True + + def init_first_update_device_replica_mapping(self): + # Check if there is no replica version difference. return first_chunk_devices_update + first_chunk_dict = self.get_first_chunk_devices_replica_update() + if first_chunk_dict is None: + return self.request_json + + # Update the updating window + self.init_update_updating_window(first_chunk_dict) + + # Prepare and return the request json + replica_num_diff_key = "replica_version_diff" + self.request_json[replica_num_diff_key] = first_chunk_dict + return self.request_json diff --git a/python/fedml/computing/scheduler/model_scheduler/device_replica_handler.py b/python/fedml/computing/scheduler/model_scheduler/device_replica_handler.py new file mode 100644 index 0000000000..d8865ed854 --- /dev/null +++ b/python/fedml/computing/scheduler/model_scheduler/device_replica_handler.py @@ -0,0 +1,138 @@ +import logging +from ..scheduler_core.compute_cache_manager import ComputeCacheManager +from ..comm_utils.container_utils import ContainerUtils +from ..comm_utils import security_utils +from .device_client_constants import ClientConstants +from .device_model_msg_object import FedMLModelMsgObject + + +class FedMLDeviceReplicaHandler: + def __init__(self, worker_id, request_json: dict): + """ + Handler on the worker to actually exec the reconciliation logic (Including add, remove, update). + + e_id: unique id (i.e. endpoint_id) for each deployment + devices_avail_gpus = {device_id1: gpu_num, device_id2: gpu_num, ...} + request_json: json from MLOps for this deployment + total_gpu_num: total number of gpus will be used for this deployment + gpu_per_replica: number of gpus required per replica + """ + self.worker_id = worker_id + self.request_json = request_json + self.request_msg_obj = FedMLModelMsgObject("replica_handler", request_json) + self.e_id = self.request_msg_obj.run_id + self.gpu_per_replica = self.request_msg_obj.gpu_per_replica + + self.replica_num_diff = self.get_diff_replica_num_frm_request_json() + self.replica_version_diff = self.get_diff_replica_version_frm_request_json() + + self.end_point_name = self.request_msg_obj.end_point_name + self.inference_model_name = self.request_msg_obj.model_name + self.model_version = self.request_msg_obj.model_version + self.model_id = self.request_msg_obj.model_id + + self.device_avail_gpus = self.get_device_avail_gpus_frm_db() + + def get_device_avail_gpus_frm_db(self): + """ + Get the available gpus from db. + """ + available_gpu_ids = ComputeCacheManager.get_instance().get_gpu_cache().get_device_available_gpu_ids( + self.worker_id) + logging.info(f"[Replica Handler] [endpoint {self.e_id} ] [worker {self.worker_id}] " + f"All device_avail_gpus: {available_gpu_ids}") + return available_gpu_ids + + def get_diff_replica_num_frm_request_json(self): + """ + Read replica_diff passing by master's request json. + Return: + { + id1_str: {"op": "add", "curr_num": 1, "target_num": 2}, + id2_str: {"op": "add", "curr_num": 1, "target_num": 2} + } + """ + if "replica_num_diff" in self.request_json and str(self.worker_id) in self.request_json["replica_num_diff"]: + return self.request_json["replica_num_diff"][str(self.worker_id)] + return None + + def get_diff_replica_version_frm_request_json(self): + """ + Read replica_diff passing by master's request json. + Return: + { + "id1": { + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"}, + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"} + }, + "id2": { + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"}, + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"} + } + } + """ + if ("replica_version_diff" in self.request_json and + str(self.worker_id) in self.request_json["replica_version_diff"]): + return self.request_json["replica_version_diff"][str(self.worker_id)] + + return None + + def reconcile_num_replica(self): + """ + To solve the conflict between different reconciliation requests. The request & delete reqs should be + executed in order and atomic (i.e. rollback). + + return (op, number of op) + """ + if not self.replica_num_diff: + logging.info(f"replica_num_diff is empty, will not reconcile.") + return None, None, None + + if self.replica_num_diff["op"] not in ["add", "remove"]: + raise ValueError(f"op should be add or remove. Got {self.replica_num_diff['op']}") + + prev_rank = self.replica_num_diff["curr_num"] - 1 + if self.replica_num_diff["op"] == "add": + assert self.replica_num_diff["target_num"] > self.replica_num_diff["curr_num"] + op, op_num = (self.replica_num_diff["op"], + self.replica_num_diff["target_num"] - self.replica_num_diff["curr_num"]) + else: + assert self.replica_num_diff["target_num"] < self.replica_num_diff["curr_num"] + op, op_num = (self.replica_num_diff["op"], + self.replica_num_diff["curr_num"] - self.replica_num_diff["target_num"]) + return prev_rank, op, op_num + + def remove_replica(self, rank): + """ + Remove replica_num replicas from device_id. + """ + running_model_name = ClientConstants.get_running_model_name( + self.end_point_name, self.inference_model_name, self.model_version, self.e_id, self.model_id, + self.worker_id) + container_prefix = ("{}".format(ClientConstants.FEDML_DEFAULT_SERVER_CONTAINER_NAME_PREFIX) + "__" + + security_utils.get_content_hash(running_model_name)) + container_name = container_prefix + "__" + str(rank) + logging.info(f"[Replica Handler] [Remove Replica] [Device {self.worker_id}] [Endpoint {self.e_id}]" + f" [Replica {rank}] [Container {container_name}]") + ContainerUtils.get_instance().remove_container(container_name) + + def reconcile_replica_version(self): + """ + Return a list of replica_rank to be updated. + Giving { + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"}, + $replica_no: {"op": "update", "new_version": "v2", "old_version": "v1"} + } + for all replicas, update the version. i.e. stop and remove the container, records in db, then start the new + container, and report when the new container is ready. + """ + replica_rank_to_update = [] + ret_op = "update" + if not self.replica_version_diff: + logging.info(f"replica_version_diff is empty, will not reconcile.") + return None, None + + for replica_no, diff in self.replica_version_diff.items(): + replica_rank_to_update.append(int(replica_no)-1) + + return replica_rank_to_update, ret_op diff --git a/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py b/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py index 41e2e5cd44..c06cccbf83 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py @@ -46,6 +46,7 @@ from ....core.mlops.mlops_utils import MLOpsUtils from ..comm_utils.constants import SchedulerConstants from .device_model_db import FedMLModelDatabase +from .device_replica_controller import FedMLDeviceReplicaController class RunnerError(BaseException): @@ -119,6 +120,9 @@ def __init__(self, args, run_id=0, request_json=None, agent_config=None, edge_id self.subscribed_topics = list() self.user_name = None + self.replica_controller = None + self.deployed_replica_payload = None + def build_dynamic_constrain_variables(self, run_id, run_config): pass @@ -348,21 +352,14 @@ def run_impl(self): logging.info("send the model inference request to slave devices...") self.check_runner_stop_event() - # handle "op:replace" - first_chunk_devices_update = self.request_json.get("first_chunk_devices_update", list()) - if len(first_chunk_devices_update) > 0: - self.send_first_scroll_update_msg(first_chunk_devices_update) - - # handle "op:add" - should_added_devices = self.send_deployment_start_request_to_edges() + # handle "op:add" && "op:remove" + devices_sent_add_or_remove_msg = self.send_deployment_start_request_to_edges() - # handle "op:delete" - self.send_deployment_delete_request_to_edges(payload=json.dumps(self.request_json), model_msg_object=None) + # handle "op:update" + devices_sent_update_remove_msg = self.send_first_scroll_update_msg() - if len(should_added_devices) == 0 and len(first_chunk_devices_update) == 0: - ''' - If just including delete op, we do not need to wait for the slave devices to finish the delete. - ''' + if len(devices_sent_add_or_remove_msg) == 0 and len(devices_sent_update_remove_msg) == 0: + # No device is added or removed, and no device is updated or removed ip = self.get_ip_address(self.request_json) master_port = os.getenv("FEDML_MASTER_PORT", None) if master_port is not None: @@ -373,10 +370,13 @@ def run_impl(self): else: model_inference_url = "http://{}:{}/api/v1/predict".format(ip, model_inference_port) - self.send_deployment_status(self.run_id, end_point_name, + self.set_runner_completed_event(run_id) + + self.send_deployment_status(run_id, end_point_name, model_name, model_inference_url, ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED) + return while True: self.check_runner_stop_event() @@ -546,12 +546,36 @@ def callback_deployment_result_message(self, topic=None, payload=None): model_name = payload_json["model_name"] model_version = payload_json["model_version"] model_status = payload_json["model_status"] + replica_no = payload_json.get("replica_no", None) # Idx start from 1 run_id_str = str(end_point_id) + + # Set redis + sqlite deployment result FedMLModelCache.get_instance().set_redis_params(self.redis_addr, self.redis_port, self.redis_password) - FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ - set_deployment_result(end_point_id, end_point_name, - model_name, model_version, - device_id, payload) + + if model_status == ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DELETED: + FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ + delete_deployment_result_with_device_id_and_replica_no( + end_point_id, end_point_name, model_name, device_id, replica_no) + elif model_status == ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED: + # add or update + FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ + set_deployment_result(end_point_id, end_point_name, + model_name, model_version, + device_id, payload, replica_no) + + # Note: To display the result in the UI, we need to save successful deployment result to the database + self.model_runner_mapping[run_id_str].deployed_replica_payload = copy.deepcopy(payload_json) + else: + assert model_status == ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED + + # Notify the replica number controller + (self.model_runner_mapping[run_id_str]. + replica_controller.callback_update_curr_replica_num_state(device_id, replica_no, model_status)) + + # Notify the replica version controller, which might trigger the next rolling update + self.send_next_scroll_update_msg(device_id, replica_no) + + # Update the global deployment result mapping if self.slave_deployment_results_mapping.get(run_id_str, None) is None: self.slave_deployment_results_mapping[run_id_str] = dict() self.slave_deployment_results_mapping[run_id_str][str(device_id)] = model_status @@ -567,77 +591,54 @@ def callback_deployment_result_message(self, topic=None, payload=None): ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED) return - all_device_id_list = request_json["device_ids"] + # all_device_id_list = request_json["device_ids"] - device_id_list = [] + # device_id_list = [] - for device in all_device_id_list: - if str(device) == str(self.edge_id): - continue - - if device in request_json["diff_devices"] and \ - (request_json["diff_devices"][device] == ServerConstants.DEVICE_DIFF_ADD_OPERATION or - request_json["diff_devices"][device] == ServerConstants.DEVICE_DIFF_REPLACE_OPERATION): - device_id_list.append(device) - - if request_json["diff_devices"].get(int(device_id), None) == ServerConstants.DEVICE_DIFF_REPLACE_OPERATION: - if model_status == ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED: - # TODO: Support rollback - return - else: - # Get record from the first message that Java mlops sent - total_device_objs_list = self.request_json["device_objs"] - device_obj_to_insert = None - - for device_obj in total_device_objs_list: - if device_obj["id"] == int(device_id): - device_obj["status"] = ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED - device_obj_to_insert = device_obj - break - if not device_obj_to_insert: - raise Exception(f"Cannot find device {device_id} in the device list {total_device_objs_list}") - - FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ - add_end_point_device_info(request_json["end_point_id"], end_point_name, - json.dumps(device_obj_to_insert)) - - self.send_next_scroll_update_msg(int(device_id)) - - if len(self.slave_deployment_results_mapping[run_id_str].keys()) >= len(device_id_list): + # for device in all_device_id_list: + # if str(device) == str(self.edge_id): + # continue + # + # if device in request_json["diff_devices"] and \ + # (request_json["diff_devices"][device] == ServerConstants.DEVICE_DIFF_ADD_OPERATION or + # request_json["diff_devices"][device] == ServerConstants.DEVICE_DIFF_REPLACE_OPERATION): + # device_id_list.append(device) + # + # # Scroll update + # if request_json["diff_devices"].get(int(device_id), None) == ServerConstants.DEVICE_DIFF_REPLACE_OPERATION: + # if model_status == ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED: + # # TODO: Support rollback + # return + # else: + # # Get record from the first message that Java mlops sent + # total_device_objs_list = self.request_json["device_objs"] + # device_obj_to_insert = None + # + # for device_obj in total_device_objs_list: + # if device_obj["id"] == int(device_id): + # device_obj["status"] = ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED + # device_obj_to_insert = device_obj + # break + # if not device_obj_to_insert: + # raise Exception(f"Cannot find device {device_id} in the device list {total_device_objs_list}") + # + # FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ + # add_end_point_device_info(request_json["end_point_id"], end_point_name, + # json.dumps(device_obj_to_insert)) + # + # self.send_next_scroll_update_msg(int(device_id)) + + # Wait for all replica's result, not device-level + if (self.model_runner_mapping[run_id_str].replica_controller.is_all_replica_num_reconciled() and + self.model_runner_mapping[run_id_str].replica_controller.is_all_replica_version_reconciled()): ''' - When all the devices have finished the add / update operation + When all the devices have finished the add / delete / update operation ''' - failed_to_deploy_all_models = False - for device_item in device_id_list: - if device_item == self.edge_id: # Skip the master - continue - status = self.slave_deployment_results_mapping[run_id_str]. \ - get(str(device_item), ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED) - if status == ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED: - failed_to_deploy_all_models = True - break - - # Failed to deploy models. - if failed_to_deploy_all_models: - # Send stage: MODEL_DEPLOYMENT_STAGE5 = "StartInferenceIngress" - self.send_deployment_stages(end_point_id, model_name, model_id, - "", - ServerConstants.MODEL_DEPLOYMENT_STAGE5["index"], - ServerConstants.MODEL_DEPLOYMENT_STAGE5["text"], - "Failed to deploy the model to all devices.") - FedMLModelDatabase.get_instance().delete_deployment_status( - run_id_str, end_point_name, model_name, model_version=model_version) - FedMLModelDatabase.get_instance().delete_deployment_result( - run_id_str, end_point_name, model_name, model_version=model_version) - - # reset slave_deployment_results_mapping, incase user might use this for redeployment - self.slave_deployment_results_mapping[run_id_str] = dict() - return - # 1. We should generate one unified inference api # Note that here we use the gateway port instead of the inference port that is used by the slave device model_config_parameters = request_json["parameters"] - inference_port = model_config_parameters.get("server_internal_port", ServerConstants.MODEL_INFERENCE_DEFAULT_PORT) + inference_port = model_config_parameters.get("server_internal_port", + ServerConstants.MODEL_INFERENCE_DEFAULT_PORT) inference_port_external = model_config_parameters.get("server_external_port", inference_port) ip = self.get_ip_address(request_json) @@ -653,58 +654,45 @@ def callback_deployment_result_message(self, topic=None, payload=None): ServerConstants.MODEL_DEPLOYMENT_STAGE5["text"], "inference url: {}".format(model_inference_url)) - # 2. We should send to MBE(ModelOps Backend) - model_slave_url = payload_json["model_url"] - payload_json["model_url"] = model_inference_url - payload_json["port"] = inference_port_external - token = FedMLModelCache.get_instance(self.redis_addr, self.redis_port).get_end_point_token(end_point_id, end_point_name, model_name) - - model_metadata = payload_json["model_metadata"] - model_inputs = model_metadata["inputs"] - ret_inputs = list() - if "type" in model_metadata and model_metadata["type"] == "default": - payload_json["input_json"] = {"end_point_name": end_point_name, - "model_name": model_name, - "token": str(token), - "inputs": model_inputs, - "outputs": []} - payload_json["output_json"] = model_metadata["outputs"] + # Prepare the result to MLOps + if self.model_runner_mapping[run_id_str].deployed_replica_payload is not None: + payload_json = self.model_runner_mapping[run_id_str].deployed_replica_payload + model_slave_url = payload_json["model_url"] + payload_json["model_url"] = model_inference_url + payload_json["port"] = inference_port_external + token = FedMLModelCache.get_instance(self.redis_addr, self.redis_port).get_end_point_token( + end_point_id, end_point_name, model_name) + + model_metadata = payload_json["model_metadata"] + model_inputs = model_metadata["inputs"] + ret_inputs = list() + if "type" in model_metadata and model_metadata["type"] == "default": + payload_json["input_json"] = {"end_point_name": end_point_name, + "model_name": model_name, + "token": str(token), + "inputs": model_inputs, + "outputs": []} + payload_json["output_json"] = model_metadata["outputs"] + else: + raise Exception(f"Unsupported model metadata type {model_metadata['type']}") + + self.send_deployment_results_with_payload(end_point_id, end_point_name, payload_json) + + payload_json_saved = payload_json + payload_json_saved["model_slave_url"] = model_slave_url + FedMLServerDataInterface.get_instance().save_job_result(end_point_id, self.edge_id, + json.dumps(payload_json_saved)) else: - # triton model, auto generate inputs - for input_item in model_inputs: - ret_item = input_item - shape = ret_item["shape"] - data_type = ret_item["datatype"] - if ServerConstants.MODEL_DATA_TYPE_MAPPING[data_type] == ServerConstants.MODEL_DATA_TYPE_INT: - for i in range(len(shape)): - if shape[i] == -1: # if input shape is dynamic, we set a default value 1 - shape[i] = 1 - ret_item["data"] = torch.randint(0, 1, shape).tolist() - else: - for i in range(len(shape)): - if shape[i] == -1: # if input shape is dynamic, we set a default value 1 - shape[i] = 1 - ret_item["data"] = torch.zeros(shape).tolist() - ret_inputs.append(ret_item) - - payload_json["input_json"] = {"end_point_name": end_point_name, - "model_name": model_name, - "token": str(token), - "inputs": {"inputs": ret_inputs}, # Nested inputs - "outputs": model_metadata["outputs"]} - payload_json["output_json"] = model_metadata["outputs"] - FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ - set_deployment_result(end_point_id, end_point_name, - model_name, model_version, - self.edge_id, json.dumps(payload_json)) + # Only remove ops + pass + FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ set_end_point_activation(end_point_id, end_point_name, True) - self.send_deployment_results_with_payload(end_point_id, end_point_name, payload_json) - payload_json_saved = payload_json - payload_json_saved["model_slave_url"] = model_slave_url - FedMLServerDataInterface.get_instance().save_job_result(end_point_id, self.edge_id, - json.dumps(payload_json_saved)) + self.send_deployment_status(end_point_id, end_point_name, + payload_json["model_name"], + model_inference_url, + ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED) self.slave_deployment_results_mapping[run_id_str] = dict() @@ -712,111 +700,19 @@ def callback_deployment_result_message(self, topic=None, payload=None): self.set_runner_completed_event(end_point_id) def callback_deployment_status_message(self, topic=None, payload=None): - # Save deployment status to local cache - topic_splits = str(topic).split('/') - device_id = topic_splits[-1] - payload_json = json.loads(payload) - end_point_id = payload_json["end_point_id"] - end_point_name = payload_json["end_point_name"] - model_name = payload_json["model_name"] - model_version = payload_json["model_version"] - inference_port = payload_json.get("inference_external_api_port", ServerConstants.MODEL_INFERENCE_DEFAULT_PORT) - run_id_str = str(end_point_id) - - model_status = payload_json["model_status"] - FedMLModelCache.get_instance().set_redis_params(self.redis_addr, self.redis_port, self.redis_password) - FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ - set_deployment_status(end_point_id, end_point_name, - model_name, model_version, - device_id, payload) - if self.slave_deployment_statuses_mapping.get(run_id_str, None) is None: - self.slave_deployment_statuses_mapping[run_id_str] = dict() - self.slave_deployment_statuses_mapping[run_id_str][device_id] = model_status - logging.info("callback_deployment_status_message: topic {}, payload {}, mapping {}.".format( - topic, payload, self.slave_deployment_statuses_mapping[run_id_str])) - - # When all deployments are finished - request_json = self.running_request_json.get(run_id_str, None) - if request_json is None: - logging.error(f"The endpoint {end_point_id} is not running.") - self.send_deployment_status( - self.run_id, end_point_name, payload_json["model_name"], "", - ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED) - return - - device_id_list = [] - for device in request_json["device_ids"]: - if str(device) == str(self.edge_id): - continue - if device in request_json["diff_devices"] and \ - (request_json["diff_devices"][device] == ServerConstants.DEVICE_DIFF_ADD_OPERATION or - request_json["diff_devices"][device] == ServerConstants.DEVICE_DIFF_REPLACE_OPERATION): - device_id_list.append(device) - - if len(self.slave_deployment_statuses_mapping[run_id_str].keys()) >= len(device_id_list): - failed_to_deploy_all_models = False - for device_item in device_id_list: - if device_item == self.edge_id: # Skip the master - continue - status = self.slave_deployment_statuses_mapping[run_id_str]. \ - get(str(device_item), ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED) - if status == ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED: - failed_to_deploy_all_models = True - break - - # Failed to deploy the model to all devices - if failed_to_deploy_all_models: - FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ - set_end_point_activation(end_point_id, end_point_name, False) - FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ - set_end_point_status(end_point_id, end_point_name, - ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED) - self.send_deployment_status(end_point_id, end_point_name, - payload_json["model_name"], "", - ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED) - - time.sleep(2) - self.cleanup_run_when_deploy_failed() - - # reset slave_deployment_statuses_mapping, incase user might use this for redeployment - self.slave_deployment_statuses_mapping[run_id_str] = dict() - return - - # Send deployment finished message to ModelOps - ip = self.get_ip_address(request_json) - master_port = os.getenv("FEDML_MASTER_PORT", None) - if master_port is not None: - inference_port = int(master_port) - model_inference_port = inference_port - if ip.startswith("http://") or ip.startswith("https://"): - model_inference_url = "{}/inference/{}".format(ip, end_point_id) - else: - model_inference_url = "http://{}:{}/inference/{}".format(ip, model_inference_port, end_point_id) - FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ - set_end_point_activation(end_point_id, end_point_name, True) - FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ - set_end_point_status(end_point_id, end_point_name, - ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED) - self.send_deployment_status(end_point_id, end_point_name, - payload_json["model_name"], - model_inference_url, - ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED) - - # Clean the status in case next deployment - self.slave_deployment_statuses_mapping[run_id_str] = dict() + # [Deprecated] Merge the logic into callback_deployment_result_message + logging.info("[Deprecated] callback_deployment_status_message: topic {}, payload {}.".format( + topic, payload)) + pass def send_deployment_start_request_to_edges(self): - run_id = self.request_json["run_id"] + # Iterate through replica_num_diff, both add and replace should be sent to the edge devices + if "replica_num_diff" not in self.request_json or self.request_json["replica_num_diff"] is None: + return [] edge_id_list = [] - for device_id in self.request_json["device_ids"]: - if device_id in self.request_json["diff_devices"] and \ - (self.request_json["diff_devices"][device_id] == ServerConstants.DEVICE_DIFF_ADD_OPERATION): - edge_id_list.append(device_id) - - logging.info("Edge ids before diff: " + str(self.request_json["device_ids"])) - logging.info("Edge ids diff: " + str(self.request_json["diff_devices"])) - logging.info("Edge ids after diff: " + str(edge_id_list)) + for device_id in self.request_json["replica_num_diff"].keys(): + edge_id_list.append(device_id) self.request_json["master_node_ip"] = self.get_ip_address(self.request_json) should_added_devices = [] @@ -1126,6 +1022,20 @@ def callback_start_deployment(self, topic, payload): time.sleep(1) if self.run_as_edge_server_and_agent: + # Replica Controller is per deployment! + replica_controller = FedMLDeviceReplicaController(self.edge_id, self.request_json) + logging.info(f"Start Diff Replica controller for run {run_id} on edge {self.edge_id}") + + # Prepare num diff + new_request_with_num_diff = replica_controller.generate_diff_to_request_json() + self.running_request_json[run_id_str] = new_request_with_num_diff + request_json = new_request_with_num_diff + + # Prepare version diff + new_request_with_version_diff = replica_controller.init_first_update_device_replica_mapping() + self.running_request_json[run_id_str] = new_request_with_version_diff + request_json = new_request_with_version_diff + server_runner = FedMLServerRunner( self.args, run_id=run_id, request_json=request_json, agent_config=self.agent_config ) @@ -1135,6 +1045,8 @@ def callback_start_deployment(self, topic, payload): server_runner.redis_addr = self.redis_addr server_runner.redis_port = self.redis_port server_runner.redis_password = self.redis_password + server_runner.replica_controller = replica_controller + self.run_process_event_map[run_id_str] = multiprocessing.Event() self.run_process_event_map[run_id_str].clear() server_runner.run_process_event = self.run_process_event_map[run_id_str] @@ -1142,6 +1054,8 @@ def callback_start_deployment(self, topic, payload): self.run_process_completed_event_map[run_id_str].clear() server_runner.run_process_completed_event = self.run_process_completed_event_map[run_id_str] self.model_runner_mapping[run_id_str] = server_runner + + # This subprocess will copy the server_runner and run it, but they are not the same object server_process = Process(target=server_runner.run, args=( self.run_process_event_map[run_id_str], self.run_process_completed_event_map[run_id_str] )) @@ -1231,99 +1145,44 @@ def should_update_device(self, payload, new_device_id): return None def init_device_update_map(self): - """ - Scroll update. - Send first scroll update message to the device(s), then the callback_deployment_result will handle the rest - """ - self.slave_update_result_mapping[self.run_id] = { - "devices_need_update": [], - "total_updated_devices": [], - "curr_update_window": [], - "max_unavailable_rate": 0.1 - } - - for device_id, device_op in self.request_json["diff_devices"].items(): - if device_op == ServerConstants.DEVICE_DIFF_REPLACE_OPERATION: - self.slave_update_result_mapping[self.run_id]["devices_need_update"].append(device_id) - - total_num = len(self.slave_update_result_mapping[self.run_id]["devices_need_update"]) - - if total_num == 0: - return - - max_unavailable_rate = self.request_json["parameters"].get("max_unavailable_rate", 0.1) - - window_size = max(1, int(total_num * max_unavailable_rate)) - - first_chunk_devices_update = \ - self.slave_update_result_mapping[self.run_id]["devices_need_update"][:window_size].copy() - - self.slave_update_result_mapping[self.run_id]["curr_update_window"] = first_chunk_devices_update - - self.request_json["first_chunk_devices_update"] = first_chunk_devices_update.copy() # to Notify sub-process + # [Deprecated] Use the replica controller to manage the device update + pass - def send_first_scroll_update_msg(self, first_chunk_devices_update): + def send_first_scroll_update_msg(self): """ + Replica-level rolling update. Delete the record of the replaced device and send the deployment msg to the devices """ - if len(first_chunk_devices_update) == 0: - return + if "replica_version_diff" not in self.request_json or self.request_json["replica_version_diff"] is None: + return [] + + first_chunk_dict = self.request_json["replica_version_diff"] # Delete the record of the replaced device - self.delete_device_info_on_master(first_chunk_devices_update) + self.delete_device_replica_info_on_master(first_chunk_dict) # Send the deployment msg to the devices, (we reuse the start_deployment msg) - for edge_id in first_chunk_devices_update: + for edge_id in first_chunk_dict.keys(): if edge_id == self.edge_id: continue # send start deployment request to each device self.send_deployment_start_request_to_edge(edge_id) - return + return list(first_chunk_dict.keys()) - def delete_device_info_on_master(self, edge_id_list_to_delete): - # Remove the record of the replaced device + def delete_device_replica_info_on_master(self, edge_id_replica_no_dict): FedMLModelCache.get_instance().set_redis_params(self.redis_addr, self.redis_port, self.redis_password) - # 1.1 Get & Delete Deployment Status in Redis / SQLite - devices_status_list = FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ - get_deployment_status_list(self.request_json["end_point_id"], self.request_json["end_point_name"], - self.request_json["model_config"]["model_name"]) - delete_devices_status_list = [] - for device_status in devices_status_list: - device_status_dict = json.loads(device_status) - if int(device_status_dict["cache_device_id"]) in edge_id_list_to_delete: - delete_devices_status_list.append(device_status) - - for delete_item in delete_devices_status_list: - FedMLModelCache.get_instance(self.redis_addr, self.redis_port).delete_deployment_status( - delete_item, self.request_json["end_point_id"], - self.request_json["end_point_name"], - self.request_json["model_config"]["model_name"] - ) - - # 1.2 Get & Delete the endpoint device info in Redis / SQLite - device_objs = FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ - get_end_point_device_info(self.request_json["run_id"]) - - if device_objs is None: - return - - total_device_objs_list = json.loads(device_objs) - for device_obj in total_device_objs_list: - if device_obj["id"] in edge_id_list_to_delete: - total_device_objs_list.remove(device_obj) - - FedMLModelCache.get_instance(self.redis_addr, self.redis_port).set_end_point_device_info( - self.request_json["end_point_id"], self.request_json["end_point_name"], - json.dumps(total_device_objs_list)) - - # 1.3 Delete the result in deployment result list in Redis / SQLite + # Remove the record of the replaced device + # [Deprecated] deployment status & device info + # Delete the result in deployment result list in Redis / SQLite device_result_list = FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ get_deployment_result_list(self.request_json["end_point_id"], self.request_json["end_point_name"], self.request_json["model_config"]["model_name"]) delete_device_result_list = [] for device_result in device_result_list: device_result_dict = json.loads(device_result) - if int(device_result_dict["cache_device_id"]) in edge_id_list_to_delete: + if (str(device_result_dict["cache_device_id"]) in edge_id_replica_no_dict.keys() and + str(device_result_dict["cache_replica_no"]) in + edge_id_replica_no_dict[str(device_result_dict["cache_device_id"])]): delete_device_result_list.append(device_result) for delete_item in delete_device_result_list: @@ -1333,48 +1192,35 @@ def delete_device_info_on_master(self, edge_id_list_to_delete): self.request_json["model_config"]["model_name"] ) - logging.info(f"Deleted the record of the replaced device {edge_id_list_to_delete}") + logging.info(f"Deleted the record of the replaced device {delete_device_result_list}") - def send_next_scroll_update_msg(self, device_id: int): - this_run_meta_data = self.slave_update_result_mapping[self.run_id] + def send_next_scroll_update_msg(self, device_id, replica_no): + if replica_no is None: + return - devices_need_update = this_run_meta_data["devices_need_update"] - devices_updated = this_run_meta_data["total_updated_devices"] - curr_update_window = this_run_meta_data["curr_update_window"] - max_unavailable_rate = this_run_meta_data["max_unavailable_rate"] + replica_controller = self.model_runner_mapping[str(self.run_id)].replica_controller - if (device_id not in devices_need_update) or (device_id in devices_updated): - # Prevent duplicate message / cross talk - # TODO: Check the cross talk if multiple run update the same device - logging.info(f"Device {device_id} is not in the update window nor need to be updated") + if replica_controller.total_replica_version_diff_num == 0: return - devices_updated.append(device_id) - curr_update_window.remove(device_id) + replica_controller.callback_update_updating_window(device_id, replica_no) - logging.info(f"Current update window {curr_update_window} after deleting: Device {device_id}") + # Decide whether to send the next scroll update + next_chunk_dict = replica_controller.get_next_chunk_devices_replica() - if len(curr_update_window) == 0: - remain_devices = list(set(devices_need_update) - set(devices_updated)) - logging.info(f"Devices need to be updated: {remain_devices}") - if len(remain_devices) == 0: # All devices are updated - return - else: - window_size = max(1, int(len(remain_devices) * max_unavailable_rate)) - edges_in_window = remain_devices[:window_size] - logging.info(f"Devices in next round window: {edges_in_window}") - curr_update_window = edges_in_window.copy() # Slide the window - self.slave_update_result_mapping[self.run_id]["curr_update_window"] = edges_in_window.copy() - - self.delete_device_info_on_master(edges_in_window) - - # Send the deployment msg to the devices, (we reuse the deployment msg) - for edge_id in edges_in_window: - if edge_id == self.edge_id: - continue - self.send_deployment_start_request_to_edge(edge_id) - else: - pass # Wait for the callback of other devices in this window + replica_controller.curr_replica_updating_window = copy.deepcopy(next_chunk_dict) + + if next_chunk_dict: + self.request_json["replica_version_diff"] = next_chunk_dict + self.delete_device_replica_info_on_master(next_chunk_dict) + + # Send the deployment msg to the devices, (we reuse the start_deployment msg) + for edge_id in next_chunk_dict.keys(): + if edge_id == self.edge_id: + continue + # send start deployment request to each device + self.send_deployment_start_request_to_edge(edge_id) + return def callback_activate_deployment(self, topic, payload): logging.info("callback_activate_deployment: topic = %s, payload = %s" % (topic, payload)) diff --git a/python/fedml/computing/scheduler/scheduler_core/endpoint_monitor_protocol.py b/python/fedml/computing/scheduler/scheduler_core/endpoint_monitor_protocol.py index 1f28acf27e..61f9e3e981 100755 --- a/python/fedml/computing/scheduler/scheduler_core/endpoint_monitor_protocol.py +++ b/python/fedml/computing/scheduler/scheduler_core/endpoint_monitor_protocol.py @@ -69,6 +69,7 @@ def __init__(self, payload): self.inference_port = payload_json.get("inference_port", None) self.device_id = payload_json.get("device_id", None) self.disable = payload_json.get("disable", None) + self.replica_no = payload_json.get("replica_no", None) class FedMLEndpointMonitorProtocol(FedMLBaseProtocol): diff --git a/python/fedml/computing/scheduler/scheduler_core/endpoint_sync_protocol.py b/python/fedml/computing/scheduler/scheduler_core/endpoint_sync_protocol.py index 545ba75650..ab707c8ff4 100755 --- a/python/fedml/computing/scheduler/scheduler_core/endpoint_sync_protocol.py +++ b/python/fedml/computing/scheduler/scheduler_core/endpoint_sync_protocol.py @@ -67,12 +67,12 @@ def send_sync_deployment_status(self, master_id, status_payload): def send_sync_inference_info( self, master_id, worker_device_id, end_point_id, end_point_name, model_name, - model_id, model_version, inference_port, disable=False): + model_id, model_version, inference_port, replica_no, disable=False): deployment_info_topic = f"{EndpointSyncMsgConstants.SLAVE_MASTER_DEPLOYMENT_INFO_MSG}/{master_id}" deployment_info_payload = { "device_id": worker_device_id, "end_point_id": end_point_id, "end_point_name": end_point_name, "model_id": model_id, "model_name": model_name, "model_version": model_version, - "inference_port": inference_port, "disable": disable} + "inference_port": inference_port, "disable": disable, "replica_no": replica_no} logging.info("send_sync_inference_port: topic {}, payload {}.".format( deployment_info_topic, deployment_info_payload)) self.client_mqtt_mgr.send_message_json(deployment_info_topic, json.dumps(deployment_info_payload)) @@ -115,92 +115,62 @@ def callback_sync_device_info(self, topic, payload): master_device_id = topic_splits[-1] deployment_info = EndpointDeviceDeploymentInfoModel(payload) - # Status - status_item_found = None - status_payload_found = None - FedMLModelCache.get_instance().set_redis_params() - status_list = FedMLModelCache.get_instance().get_deployment_status_list( - deployment_info.endpoint_id, deployment_info.endpoint_name, deployment_info.model_name) - for status_item in status_list: - cache_device_id, status_payload = FedMLModelCache.get_instance().get_status_item_info(status_item) - if str(cache_device_id) == str(deployment_info.device_id): - status_item_found = status_item - status_payload_found = status_payload - model_status = status_payload.get("model_status") - break + # Status [Deprecated] - if status_item_found is not None: - #print(f"status_item_found {status_item_found}, status_payload_found {status_payload_found}") - # Delete Status - FedMLModelCache.get_instance().delete_deployment_status( - status_item_found, deployment_info.endpoint_id, deployment_info.endpoint_name, - deployment_info.model_name) - - if deployment_info.disable: - status_payload_found["model_status"] = ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_UPDATING - else: - status_payload_found["model_status"] = ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED - - # Update Status - model_url_parsed = urlparse(status_payload_found.get("model_url", "")) - status_payload_found["model_url"] = f"http://{model_url_parsed.hostname}:{deployment_info.inference_port}{model_url_parsed.path}" - status_payload_found["inference_port"] = deployment_info.inference_port - FedMLModelCache.get_instance().set_deployment_status( - deployment_info.endpoint_id, deployment_info.endpoint_name, deployment_info.model_name, - deployment_info.model_version, deployment_info.device_id, json.dumps(status_payload_found)) - - # Result + # Find the existed result in the local db result_item_found = None result_payload_found = None FedMLModelCache.get_instance().set_redis_params() result_list = FedMLModelCache.get_instance().get_deployment_result_list( deployment_info.endpoint_id, deployment_info.endpoint_name, deployment_info.model_name) for result_item in result_list: - cache_device_id, result_payload = FedMLModelCache.get_instance().get_result_item_info(result_item) - if str(cache_device_id) == str(deployment_info.device_id): + cache_device_id, replica_no, result_payload = ( + FedMLModelCache.get_instance().get_result_item_info(result_item)) + if str(cache_device_id) == str(deployment_info.device_id) and replica_no == deployment_info.replica_no: result_item_found = result_item result_payload_found = result_payload break + # Update the replica element if result_item_found is not None: - #print(f"result_item_found {result_item_found}, result_payload_found {result_payload_found}") + # print(f"result_item_found {result_item_found}, result_payload_found {result_payload_found}") + + # Delete the replica info from the local redis + # TODO: Delete also in the sqlite FedMLModelCache.get_instance().delete_deployment_result( result_item_found, deployment_info.endpoint_id, deployment_info.endpoint_name, deployment_info.model_name) if deployment_info.disable: + # This replica is down result_payload_found["model_status"] = ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_UPDATING else: result_payload_found["model_status"] = ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED model_url_parsed = urlparse(result_payload_found.get("model_url", "")) - result_payload_found["model_url"] = f"http://{model_url_parsed.hostname}:{deployment_info.inference_port}{model_url_parsed.path}" + result_payload_found["model_url"] = (f"http://{model_url_parsed.hostname}:{deployment_info.inference_port}" + f"{model_url_parsed.path}") result_payload_found["inference_port"] = deployment_info.inference_port FedMLModelCache.get_instance().set_deployment_result( deployment_info.endpoint_id, deployment_info.endpoint_name, deployment_info.model_name, - deployment_info.model_version, deployment_info.device_id, json.dumps(result_payload_found)) + deployment_info.model_version, deployment_info.device_id, json.dumps(result_payload_found), + deployment_info.replica_no) def set_local_deployment_status_result( self, endpoint_id, endpoint_name, model_name, model_version, device_id, - inference_port, status_payload, result_payload): - ''' + inference_port, status_payload, result_payload, replica_no): + """ The result and status are saved in the local sqlite table. They both belong to the table deployment_result_info; deployment_result column is used to save the result; deployment_status column is used to save the status. - ''' - if status_payload is not None: - model_url_parsed = urlparse(status_payload.get("model_url", "")) - status_payload["model_url"] = f"http://{model_url_parsed.hostname}:{inference_port}{model_url_parsed.path}" - status_payload["inference_port"] = inference_port - FedMLModelDatabase().get_instance().set_deployment_status( - endpoint_id, endpoint_name, model_name, - model_version=None, device_id=device_id, deployment_status=json.dumps(status_payload)) - + """ + # status_payload is deprecated + # result_payload if result_payload is not None: model_url_parsed = urlparse(result_payload.get("model_url", "")) result_payload["model_url"] = f"http://{model_url_parsed.hostname}:{inference_port}{model_url_parsed.path}" result_payload["inference_port"] = inference_port FedMLModelDatabase.get_instance().set_deployment_result( - endpoint_id, endpoint_name, model_name, - model_version=None, device_id=device_id, deployment_result=json.dumps(result_payload)) + endpoint_id, endpoint_name, model_name, model_version=None, device_id=device_id, + deployment_result=json.dumps(result_payload), replica_no=replica_no) diff --git a/python/fedml/core/mlops/mlops_runtime_log.py b/python/fedml/core/mlops/mlops_runtime_log.py index afc454dbb7..409feb2bb9 100644 --- a/python/fedml/core/mlops/mlops_runtime_log.py +++ b/python/fedml/core/mlops/mlops_runtime_log.py @@ -11,7 +11,7 @@ from fedml import mlops from .mlops_utils import MLOpsUtils -LOG_LEVEL = logging.CRITICAL +LOG_LEVEL = logging.INFO class MLOpsFormatter(logging.Formatter): converter = datetime.datetime.utcfromtimestamp diff --git a/python/fedml/core/mlops/mlops_runtime_log_daemon.py b/python/fedml/core/mlops/mlops_runtime_log_daemon.py index 0f191f0c66..401de34e93 100644 --- a/python/fedml/core/mlops/mlops_runtime_log_daemon.py +++ b/python/fedml/core/mlops/mlops_runtime_log_daemon.py @@ -265,6 +265,7 @@ def log_process(self, process_event): print("Log Process exits normally.") def log_relocation(self): + # move the log file pointer to the last uploaded line log_line_count = self.log_line_index self.log_uploaded_line_index = self.log_line_index while log_line_count > 0: @@ -298,6 +299,7 @@ def log_read(self): line_count = 0 log_lines = [] while True: + # readlines will ignore those lines has been read using readline log_line = self.log_file.readlines() if len(log_line) <= 0: break From 35685da94a422793009fb29dccbd4f36b17ec148 Mon Sep 17 00:00:00 2001 From: Raphael Jin Date: Mon, 11 Mar 2024 18:59:27 -0400 Subject: [PATCH 070/135] [Deploy] Fix endpoint deletion logic. --- .../model_scheduler/device_client_runner.py | 4 +- .../model_scheduler/device_model_cache.py | 3 +- .../device_model_deployment.py | 10 ++++- .../model_scheduler/device_server_runner.py | 41 +++++++------------ 4 files changed, 28 insertions(+), 30 deletions(-) diff --git a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py index b99e0bea58..d0286d83e3 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py @@ -977,11 +977,12 @@ def set_runner_completed_event(self, run_id): self.model_runner_mapping.pop(run_id_str) def callback_delete_deployment(self, topic, payload): - logging.info("callback_delete_deployment: topic = %s, payload = %s" % (topic, payload)) + logging.info("[Worker] callback_delete_deployment") # Parse payload as the model message object. model_msg_object = FedMLModelMsgObject(topic, payload) + # Delete all replicas on this device try: ClientConstants.remove_deployment( model_msg_object.end_point_name, model_msg_object.model_name, model_msg_object.model_version, @@ -1000,6 +1001,7 @@ def callback_delete_deployment(self, topic, payload): try: self.running_request_json.pop(str(model_msg_object.run_id)) except Exception as e: + logging.error(f"Error when removing running_request_json: {traceback.format_exc()}") pass FedMLClientDataInterface.get_instance().delete_job_from_db(model_msg_object.run_id) diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py b/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py index a58334a477..d07192de04 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py @@ -409,7 +409,7 @@ def get_replica_gpu_ids(self, end_point_id, end_point_name, model_name, device_i def delete_end_point(self, end_point_id, end_point_name, model_name, model_version): try: - print("Will Delete the realated redis keys permanently") + logging.info("Will Delete the related redis keys permanently") self.redis_connection.expire(self.get_deployment_result_key(end_point_id, end_point_name, model_name), ServerConstants.MODEL_CACHE_KEY_EXPIRE_TIME) self.redis_connection.expire(self.get_deployment_status_key(end_point_id, end_point_name, model_name), ServerConstants.MODEL_CACHE_KEY_EXPIRE_TIME) self.redis_connection.expire(self.get_monitor_metrics_key(end_point_id, end_point_name, model_name, model_version), ServerConstants.MODEL_CACHE_KEY_EXPIRE_TIME) @@ -419,6 +419,7 @@ def delete_end_point(self, end_point_id, end_point_name, model_name, model_versi self.redis_connection.expire(self.get_end_point_activation_key(end_point_id), ServerConstants.MODEL_CACHE_KEY_EXPIRE_TIME) self.redis_connection.expire(self.get_end_point_status_key(end_point_id), ServerConstants.MODEL_CACHE_KEY_EXPIRE_TIME) except Exception as e: + logging.error(f"error when deleting the redis keys: {e}") pass def get_end_point_activation(self, end_point_id): diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_deployment.py b/python/fedml/computing/scheduler/model_scheduler/device_model_deployment.py index 7356724277..f783d2d584 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_deployment.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_deployment.py @@ -522,8 +522,14 @@ def log_deployment_result(end_point_id, model_id, cmd_container_name, cmd_type, break if container_obj is not None: - out_logs = container_obj.logs(stdout=True, stderr=False, stream=False, follow=False, since=last_log_time) - err_logs = container_obj.logs(stdout=False, stderr=True, stream=False, follow=False, since=last_log_time) + try: + out_logs = container_obj.logs(stdout=True, stderr=False, stream=False, follow=False, + since=last_log_time) + err_logs = container_obj.logs(stdout=False, stderr=True, stream=False, follow=False, + since=last_log_time) + except Exception as e: + logging.error(f"Failed to get the logs from the container with exception {e}") + pass last_log_time = datetime.datetime.now() diff --git a/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py b/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py index c06cccbf83..9b6da3a699 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py @@ -23,6 +23,7 @@ import fedml from fedml.computing.scheduler.comm_utils.run_process_utils import RunProcessUtils +from fedml.computing.scheduler.scheduler_core.compute_cache_manager import ComputeCacheManager from ..comm_utils import sys_utils from .device_server_data_interface import FedMLServerDataInterface @@ -762,25 +763,7 @@ def send_deployment_delete_request_to_edges(self, payload, model_msg_object): FedMLModelCache.get_instance().set_redis_params(self.redis_addr, self.redis_port, self.redis_password) - # 1. Get & Delete Deployment Status in Redis / SQLite - devices_status_list = FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ - get_deployment_status_list(self.request_json["end_point_id"], - self.request_json["end_point_name"], - self.request_json["model_config"]["model_name"]) - delete_devices_status_list = [] - for device_status in devices_status_list: - device_status_dict = json.loads(device_status) - if int(device_status_dict["cache_device_id"]) in edge_id_list_to_delete: - delete_devices_status_list.append(device_status) - - for delete_item in delete_devices_status_list: - FedMLModelCache.get_instance(self.redis_addr, self.redis_port).delete_deployment_status( - delete_item, self.request_json["end_point_id"], - self.request_json["end_point_name"], - self.request_json["model_config"]["model_name"] - ) - - # 2. Get & Delete the endpoint device info in Redis / SQLite + # 1. Get & Delete the endpoint device info in Redis / SQLite device_objs = FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ get_end_point_device_info(self.request_json["run_id"]) @@ -796,7 +779,7 @@ def send_deployment_delete_request_to_edges(self, payload, model_msg_object): self.request_json["end_point_id"], self.request_json["end_point_name"], json.dumps(total_device_objs_list)) - # 3. Delete the result in deployment result list in Redis / SQLite + # 2 Delete the result in deployment result list in Redis / SQLite device_result_list = FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ get_deployment_result_list(self.request_json["end_point_id"], self.request_json["end_point_name"], @@ -836,7 +819,16 @@ def send_deployment_delete_request_to_edges(self, payload, model_msg_object): with open(os.path.expanduser(debug_log_path), "w") as f: f.write(str(payload)) + # Get model master node id from redis + ComputeCacheManager.get_instance().set_redis_params() + edge_device_id, model_master_device_id, model_slave_device_id = \ + ComputeCacheManager.get_instance().get_gpu_cache().get_edge_model_id_map(self.request_json["end_point_id"]) + + # Remove the model_master_device_id + edge_id_list_to_delete.remove(model_master_device_id) + logging.info("Device ids to be deleted: " + str(edge_id_list_to_delete)) + for edge_id in edge_id_list_to_delete: if edge_id == self.edge_id: continue @@ -1273,8 +1265,7 @@ def set_runner_completed_event(self, run_id): self.model_runner_mapping.pop(run_id_str) def callback_delete_deployment(self, topic, payload): - logging.info("callback_delete_deployment: topic = %s, payload = %s" % (topic, payload)) - + logging.info("[Master] callback_delete_deployment") # Parse payload as the model message object. model_msg_object = FedMLModelMsgObject(topic, payload) @@ -1284,7 +1275,8 @@ def callback_delete_deployment(self, topic, payload): set_end_point_activation(model_msg_object.inference_end_point_id, model_msg_object.end_point_name, False) FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ - delete_end_point(model_msg_object.inference_end_point_id, model_msg_object.end_point_name, model_msg_object.model_name, model_msg_object.model_version) + delete_end_point(model_msg_object.inference_end_point_id, model_msg_object.end_point_name, + model_msg_object.model_name, model_msg_object.model_version) self.send_deployment_delete_request_to_edges(payload, model_msg_object) @@ -1295,9 +1287,6 @@ def callback_delete_deployment(self, topic, payload): model_msg_object.model_version) FedMLServerDataInterface.get_instance().delete_job_from_db(model_msg_object.run_id) - FedMLModelDatabase.get_instance().delete_deployment_status( - model_msg_object.run_id, model_msg_object.end_point_name, model_msg_object.model_name, - model_version=model_msg_object.model_version) FedMLModelDatabase.get_instance().delete_deployment_result( model_msg_object.run_id, model_msg_object.end_point_name, model_msg_object.model_name, model_version=model_msg_object.model_version) From 4a758067577df437edcbbd773eaca1568353a471 Mon Sep 17 00:00:00 2001 From: Raphael Jin Date: Tue, 12 Mar 2024 19:38:59 -0400 Subject: [PATCH 071/135] [Deploy] Fix logs logic. --- .../scheduler/comm_utils/container_utils.py | 12 +++++ .../scheduler/comm_utils/job_monitor.py | 53 ++++++++++++------ .../model_scheduler/device_server_runner.py | 54 ++++--------------- 3 files changed, 59 insertions(+), 60 deletions(-) diff --git a/python/fedml/computing/scheduler/comm_utils/container_utils.py b/python/fedml/computing/scheduler/comm_utils/container_utils.py index cf2942c862..48f21373dc 100644 --- a/python/fedml/computing/scheduler/comm_utils/container_utils.py +++ b/python/fedml/computing/scheduler/comm_utils/container_utils.py @@ -56,6 +56,18 @@ def get_container_logs(self, container_name): logs_content = sys_utils.decode_our_err_result(logs_content) return logs_content + def get_container_logs_since(self, container_name, since_time: int): + container_obj = self.get_docker_object(container_name) + if container_obj is None: + return None + + logs_content = container_obj.logs(stdout=True, stderr=True, stream=False, follow=False, since=since_time) + if logs_content is None: + return None + + logs_content = sys_utils.decode_our_err_result(logs_content) + return logs_content + def remove_container(self, container_name): container_obj = self.get_docker_object(container_name) if container_obj is None: diff --git a/python/fedml/computing/scheduler/comm_utils/job_monitor.py b/python/fedml/computing/scheduler/comm_utils/job_monitor.py index f97e92cf7f..28afab7b08 100644 --- a/python/fedml/computing/scheduler/comm_utils/job_monitor.py +++ b/python/fedml/computing/scheduler/comm_utils/job_monitor.py @@ -55,6 +55,12 @@ def __init__(self): self.is_first_inference_on_gateway = True if not hasattr(self, "last_time_on_inference_gateway"): self.last_time_on_inference_gateway = None + if not hasattr(self, "replica_log_channels"): + """ + {$job_id: {$edge_id: {$replica_no: $channel_info}}} + channel_info: {"docker_last_time_stamp": int} + """ + self.replica_log_channels = dict() @staticmethod def get_instance(): @@ -738,24 +744,41 @@ def monitor_endpoint_logs(self): for i in range(num_containers): endpoint_container_name = endpoint_container_name_prefix + f"__{i}" - endpoint_logs = ContainerUtils.get_instance().get_container_logs(endpoint_container_name) - if endpoint_logs is None: + if job.job_id in self.replica_log_channels and \ + job.edge_id in self.replica_log_channels[job.job_id] and \ + i in self.replica_log_channels[job.job_id][job.edge_id]: + # Get log since last time stamp + channel_info = self.replica_log_channels[job.job_id][job.edge_id][i] + if channel_info.get("docker_last_time_stamp") is not None: + endpoint_logs = ContainerUtils.get_instance().get_container_logs_since( + endpoint_container_name, since_time=channel_info.get("docker_last_time_stamp")) + if endpoint_logs is not None: + channel_info["docker_last_time_stamp"] = int(time.time()) + else: + endpoint_logs = ContainerUtils.get_instance().get_container_logs(endpoint_container_name) + if endpoint_logs is not None: + channel_info["docker_last_time_stamp"] = int(time.time()) + else: + # First time to get the logs + self.replica_log_channels[job.job_id] = self.replica_log_channels.get(job.job_id, dict()) + self.replica_log_channels[job.job_id][job.edge_id] = self.replica_log_channels[job.job_id].get( + job.edge_id, dict()) + self.replica_log_channels[job.job_id][job.edge_id][i] = dict() + self.replica_log_channels[job.job_id][job.edge_id][i]["docker_last_time_stamp"] = ( + int(time.time())) + endpoint_logs = ContainerUtils.get_instance().get_container_logs(endpoint_container_name) + + if (endpoint_logs is None or endpoint_logs == "\n" or endpoint_logs == "\r\n" or + endpoint_logs == "\r" or endpoint_logs == "" or endpoint_logs == " "): continue + is_job_container_running = True - # Rewrite container logs to the log file - if i == 0: - with open(log_file_path, "w") as f: - pass - # f.write(f"[FedML Log Service] [Device {job.edge_id}] [Rank {i}] Start.\n") - # f.write(endpoint_logs) - # f.write(f"[FedML Log Service] [Device {job.edge_id}] [Rank {i}] End.\n") - else: - with open(log_file_path, "a") as f: - pass - # f.write(f"[FedML Log Service] [Device {job.edge_id}] [Rank {i}] Start.\n") - # f.write(endpoint_logs) - # f.write(f"[FedML Log Service] [Device {job.edge_id}] [Rank {i}] End.\n") + # Append containers log to the same log file (as they are in the same job & device) + with open(log_file_path, "a") as f: + f.write(f"[FedML Log Service] >>>>>>>> [Rank {i}] Start. >>>>>>>> \n") + f.write(endpoint_logs) + f.write(f"[FedML Log Service] <<<<<<<< [Rank {i}] End. <<<<<<<< \n") if is_job_container_running and not MLOpsRuntimeLogDaemon.get_instance(fedml_args). \ is_log_processor_running(job.job_id, int(job.edge_id)): diff --git a/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py b/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py index 9b6da3a699..b21179237c 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py @@ -592,43 +592,6 @@ def callback_deployment_result_message(self, topic=None, payload=None): ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED) return - # all_device_id_list = request_json["device_ids"] - - # device_id_list = [] - - # for device in all_device_id_list: - # if str(device) == str(self.edge_id): - # continue - # - # if device in request_json["diff_devices"] and \ - # (request_json["diff_devices"][device] == ServerConstants.DEVICE_DIFF_ADD_OPERATION or - # request_json["diff_devices"][device] == ServerConstants.DEVICE_DIFF_REPLACE_OPERATION): - # device_id_list.append(device) - # - # # Scroll update - # if request_json["diff_devices"].get(int(device_id), None) == ServerConstants.DEVICE_DIFF_REPLACE_OPERATION: - # if model_status == ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED: - # # TODO: Support rollback - # return - # else: - # # Get record from the first message that Java mlops sent - # total_device_objs_list = self.request_json["device_objs"] - # device_obj_to_insert = None - # - # for device_obj in total_device_objs_list: - # if device_obj["id"] == int(device_id): - # device_obj["status"] = ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED - # device_obj_to_insert = device_obj - # break - # if not device_obj_to_insert: - # raise Exception(f"Cannot find device {device_id} in the device list {total_device_objs_list}") - # - # FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ - # add_end_point_device_info(request_json["end_point_id"], end_point_name, - # json.dumps(device_obj_to_insert)) - # - # self.send_next_scroll_update_msg(int(device_id)) - # Wait for all replica's result, not device-level if (self.model_runner_mapping[run_id_str].replica_controller.is_all_replica_num_reconciled() and self.model_runner_mapping[run_id_str].replica_controller.is_all_replica_version_reconciled()): @@ -684,7 +647,7 @@ def callback_deployment_result_message(self, topic=None, payload=None): FedMLServerDataInterface.get_instance().save_job_result(end_point_id, self.edge_id, json.dumps(payload_json_saved)) else: - # Only remove ops + # Arrive here because only contains remove ops, so we do not need to update the model metadata pass FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ @@ -822,7 +785,8 @@ def send_deployment_delete_request_to_edges(self, payload, model_msg_object): # Get model master node id from redis ComputeCacheManager.get_instance().set_redis_params() edge_device_id, model_master_device_id, model_slave_device_id = \ - ComputeCacheManager.get_instance().get_gpu_cache().get_edge_model_id_map(self.request_json["end_point_id"]) + ComputeCacheManager.get_instance().get_gpu_cache().get_edge_model_id_map( + model_msg_object.inference_end_point_id) # Remove the model_master_device_id edge_id_list_to_delete.remove(model_master_device_id) @@ -995,13 +959,11 @@ def callback_start_deployment(self, topic, payload): self.subscribe_slave_devices_message(request_json) # Send stage: MODEL_DEPLOYMENT_STAGE1 = "Received" - time.sleep(2) self.send_deployment_stages(self.run_id, model_name, model_id, "", ServerConstants.MODEL_DEPLOYMENT_STAGE1["index"], ServerConstants.MODEL_DEPLOYMENT_STAGE1["text"], "Received request for end point {}".format(run_id)) - time.sleep(1) # Send stage: MODEL_DEPLOYMENT_STAGE2 = "Initializing" self.send_deployment_stages(self.run_id, model_name, model_id, @@ -1011,7 +973,6 @@ def callback_start_deployment(self, topic, payload): ServerConstants.MODEL_DEPLOYMENT_STAGE2["text"]) ServerConstants.save_runner_infos(self.args.device_id + "." + self.args.os_name, self.edge_id, run_id=run_id) - time.sleep(1) if self.run_as_edge_server_and_agent: # Replica Controller is per deployment! @@ -1318,7 +1279,7 @@ def send_deployment_results(self, end_point_id, end_point_name, "input_json": input_json, "output_json": output_json, "timestamp": int(format(time.time_ns() / 1000.0, '.0f'))} - logging.info(f"[Server] deployment_results_payload to mlops: {deployment_results_payload}") + logging.info(f"[Master] deployment_results_payload is sent to mlops: {deployment_results_payload}") self.client_mqtt_mgr.send_message_json(deployment_results_topic, json.dumps(deployment_results_payload)) self.client_mqtt_mgr.send_message_json(deployment_results_topic_prefix, json.dumps(deployment_results_payload)) @@ -1331,7 +1292,7 @@ def send_deployment_status(self, end_point_id, end_point_name, model_name, model "model_url": model_inference_url, "model_status": model_status, "timestamp": int(format(time.time_ns() / 1000.0, '.0f'))} - logging.info(f"[Server] deployment_status_payload to mlops: {deployment_status_payload}") + logging.info(f"[Master] deployment_status_payload is sent to mlops: {deployment_status_payload}") self.client_mqtt_mgr.send_message_json(deployment_status_topic, json.dumps(deployment_status_payload)) self.client_mqtt_mgr.send_message_json(deployment_status_topic_prefix, json.dumps(deployment_status_payload)) @@ -1348,11 +1309,14 @@ def send_deployment_stages(self, end_point_id, model_name, model_id, model_infer "model_stage_title": model_stages_title, "model_stage_detail": model_stage_detail, "timestamp": int(format(time.time_ns() / 1000.0, '.0f'))} - logging.info("-------- Stages{}:{} --------".format(model_stages_index, deployment_stages_payload)) self.client_mqtt_mgr.send_message_json(deployment_stages_topic, json.dumps(deployment_stages_payload)) self.client_mqtt_mgr.send_message_json(deployment_stages_topic_prefix, json.dumps(deployment_stages_payload)) + logging.info(f"-------- Stages has been sent to mlops with stage {model_stages_index} and " + f"payload {deployment_stages_payload}") + time.sleep(2) + def on_client_mqtt_disconnected(self, mqtt_client_object): if self.client_mqtt_lock is None: self.client_mqtt_lock = threading.Lock() From bb8c93eca4ddd4311fc83156251991355071fb7e Mon Sep 17 00:00:00 2001 From: Raphael Jin Date: Wed, 13 Mar 2024 14:34:40 -0700 Subject: [PATCH 072/135] [Deploy] Pass down gpu per replica; Add example --- .../deploy/dummy_gpu_occupier/config.yaml | 9 ++++++ .../dummy_gpu_occupier/src/serve_main.py | 32 +++++++++++++++++++ .../model_scheduler/device_client_runner.py | 8 +++-- .../device_model_deployment.py | 18 +++++------ 4 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 python/examples/deploy/dummy_gpu_occupier/config.yaml create mode 100644 python/examples/deploy/dummy_gpu_occupier/src/serve_main.py diff --git a/python/examples/deploy/dummy_gpu_occupier/config.yaml b/python/examples/deploy/dummy_gpu_occupier/config.yaml new file mode 100644 index 0000000000..e5a2343c4b --- /dev/null +++ b/python/examples/deploy/dummy_gpu_occupier/config.yaml @@ -0,0 +1,9 @@ +workspace: "./src" +entry_point: "serve_main.py" +bootstrap: | + echo "Bootstrap start..." + sleep 5 + echo "Bootstrap finished" + +auto_detect_public_ip: true +use_gpu: true \ No newline at end of file diff --git a/python/examples/deploy/dummy_gpu_occupier/src/serve_main.py b/python/examples/deploy/dummy_gpu_occupier/src/serve_main.py new file mode 100644 index 0000000000..dee73a0966 --- /dev/null +++ b/python/examples/deploy/dummy_gpu_occupier/src/serve_main.py @@ -0,0 +1,32 @@ +from fedml.serving import FedMLPredictor +from fedml.serving import FedMLInferenceRunner +import uuid +import torch + +# Calculate the number of elements +num_elements = 1_073_741_824 // 4 # using integer division for whole elements + + +class DummyPredictor(FedMLPredictor): + def __init__(self): + super().__init__() + # Create a tensor with these many elements + tensor = torch.empty(num_elements, dtype=torch.float32) + + # Move the tensor to GPU + tensor_gpu = tensor.cuda() + + # for debug + with open("/tmp/dummy_gpu_occupier.txt", "w") as f: + f.write("GPU is occupied") + + self.worker_id = uuid.uuid4() + + def predict(self, request): + return {f"AlohaV0From{self.worker_id}": request} + + +if __name__ == "__main__": + predictor = DummyPredictor() + fedml_inference_runner = FedMLInferenceRunner(predictor) + fedml_inference_runner.run() diff --git a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py index d0286d83e3..14b29d3c0c 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py @@ -463,7 +463,9 @@ def run_impl(self): self.model_is_from_open, model_config_parameters, model_from_open, token, - master_ip, self.edge_id, master_device_id=device_ids[0], replica_rank=rank) + master_ip, self.edge_id, master_device_id=device_ids[0], replica_rank=rank, + gpu_per_replica=int(self.replica_handler.gpu_per_replica) + ) except Exception as e: inference_output_url = "" logging.error(f"Exception at deployment: {traceback.format_exc()}") @@ -588,7 +590,9 @@ def run_impl(self): self.model_is_from_open, model_config_parameters, model_from_open, token, - master_ip, self.edge_id, master_device_id=device_ids[0], replica_rank=rank) + master_ip, self.edge_id, master_device_id=device_ids[0], replica_rank=rank, + gpu_per_replica=int(self.replica_handler.gpu_per_replica) + ) except Exception as e: inference_output_url = "" logging.error(f"Exception at deployment: {traceback.format_exc()}") diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_deployment.py b/python/fedml/computing/scheduler/model_scheduler/device_model_deployment.py index f783d2d584..7477795e1c 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_deployment.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_deployment.py @@ -71,14 +71,15 @@ def start_deployment(end_point_id, end_point_name, model_id, model_version, inference_use_gpu, inference_memory_size, inference_convertor_image, inference_server_image, infer_host, model_is_from_open, model_params, - model_from_open, token, master_ip, edge_id, master_device_id=None, replica_rank=0): + model_from_open, token, master_ip, edge_id, master_device_id=None, replica_rank=0, + gpu_per_replica=1): logging.info("Model deployment is starting...") sudo_prefix = "sudo " sys_name = platform.system() if sys_name == "Darwin": sudo_prefix = "" - num_gpus = 0 + num_gpus = gpu_per_replica # Real gpu per replica (container) gpu_ids, gpu_attach_cmd = None, "" running_model_name = ClientConstants.get_running_model_name( @@ -93,14 +94,14 @@ def start_deployment(end_point_id, end_point_name, model_id, model_version, with open(model_config_path, 'r') as file: config = yaml.safe_load(file) # Resource related - use_gpu = config.get('use_gpu', False) + use_gpu = config.get('use_gpu', True) in_gpu_ids = config.get('gpu_ids', gpu_ids) - num_gpus = config.get('num_gpus', None) + num_gpus_frm_yml = config.get('num_gpus', None) if not use_gpu: num_gpus = 0 else: - if num_gpus is None: - num_gpus = len(in_gpu_ids) if in_gpu_ids is not None else 1 + if num_gpus_frm_yml is not None: + num_gpus = int(num_gpus_frm_yml) usr_indicated_wait_time = config.get('deploy_timeout', 900) usr_indicated_worker_port = config.get('worker_port', "") if usr_indicated_worker_port == "": @@ -190,6 +191,7 @@ def start_deployment(end_point_id, end_point_name, model_id, model_version, FedMLModelCache.get_instance().set_redis_params() FedMLModelCache.get_instance().set_replica_gpu_ids( end_point_id, end_point_name, inference_model_name, edge_id, replica_rank+1, gpu_ids) + logging.info("GPU ids allocated: {}".format(gpu_ids)) logging.info("move converted model to serving dir for inference...") model_serving_dir = ClientConstants.get_model_serving_dir() @@ -550,9 +552,7 @@ def log_deployment_result(end_point_id, model_id, cmd_container_name, cmd_type, logging.info(f"Logs from docker: {format(out_logs)}") if container_obj.status == "exited": - logging.info("Container {} has exited, automatically" - " remove it ...".format(cmd_container_name)) - client.api.remove_container(container_obj.id, v=True, force=True) + logging.info("Container {} has exited".format(cmd_container_name)) break # should_exit_logs will ping the inference container From e912c288db0963adeccc3aeef9ec44cafcaf2831 Mon Sep 17 00:00:00 2001 From: Raphael Jin Date: Wed, 13 Mar 2024 14:56:45 -0700 Subject: [PATCH 073/135] [Deploy] Fix load balance logic. --- .../scheduler/model_scheduler/device_model_cache.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py b/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py index d07192de04..193d26303e 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py @@ -234,7 +234,7 @@ def get_result_item_info(self, result_item): def get_idle_device(self, end_point_id, end_point_name, model_name, model_version, - check_end_point_status=True): + check_end_point_status=True, limit_specific_model_version=False): # Deprecated the model status logic, query directly from the deployment result list idle_device_list = list() @@ -247,11 +247,9 @@ def get_idle_device(self, end_point_id, end_point_name, found_model_name = result_payload["model_name"] found_model_version = result_payload["model_version"] - logging.info(result_payload["model_status"]) - if (str(found_end_point_id) == str(end_point_id) and found_end_point_name == end_point_name and found_model_name == model_name and - (found_model_version == model_version or model_version == "*")): + (not limit_specific_model_version or found_model_version == model_version)): if "model_status" in result_payload and result_payload["model_status"] == "DEPLOYED": idle_device_list.append({"device_id": device_id, "end_point_id": end_point_id}) From f7e617ef1f683ea1b3c94a47bd613707bc731716 Mon Sep 17 00:00:00 2001 From: Raphael Jin Date: Wed, 13 Mar 2024 15:40:10 -0700 Subject: [PATCH 074/135] [Deploy] Fix scenario scale to devices that has not deployed. --- .../scheduler/model_scheduler/device_model_cache.py | 3 +++ .../scheduler/model_scheduler/device_model_inference.py | 3 ++- .../scheduler/model_scheduler/device_replica_controller.py | 5 ++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py b/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py index 193d26303e..f637ccde1d 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py @@ -255,6 +255,9 @@ def get_idle_device(self, end_point_id, end_point_name, logging.info(f"{len(idle_device_list)} devices has this model on it: {idle_device_list}") + if len(idle_device_list) <= 0: + return None, None + # # Randomly shuffle # shuffle the list of deployed devices and get the first one as the target idle device. # if len(idle_device_list) <= 0: diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_inference.py b/python/fedml/computing/scheduler/model_scheduler/device_model_inference.py index 3787e35b80..faa16e7b4c 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_inference.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_inference.py @@ -176,7 +176,8 @@ async def _predict( idle_device, end_point_id, model_id, model_name, model_version, inference_host, inference_output_url = \ found_idle_inference_device(in_end_point_id, in_end_point_name, in_model_name, in_model_version) if idle_device is None or idle_device == "": - return {"error": True, "error_code": status.HTTP_404_NOT_FOUND, "message": "can not found the active endpoint."} + return {"error": True, "error_code": status.HTTP_404_NOT_FOUND, + "message": "can not found active inference worker for this endpoint."} # Start timing for model metrics model_metrics = FedMLModelMetrics(end_point_id, in_end_point_name, diff --git a/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py b/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py index 261da73028..924109ce9b 100644 --- a/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py @@ -117,7 +117,10 @@ def diff_target_curr_replica_num_impl(target_replica_state, curr_replica_state): return diff_target_curr_replica_num for id, target_num in target_replica_state.items(): - if target_num > curr_replica_state[id]: + if id not in curr_replica_state: + # In one scale-out operation, the device may not be deployed yet. + diff_target_curr_replica_num[id] = {"op": "add", "curr_num": 0, "target_num": target_num} + elif target_num > curr_replica_state[id]: diff_target_curr_replica_num[id] = {"op": "add", "curr_num": curr_replica_state[id], "target_num": target_num} elif target_num < curr_replica_state[id]: From 619256457bbba4d10d1e45cf285cc9e4e8ad06e7 Mon Sep 17 00:00:00 2001 From: Raphael Jin Date: Wed, 13 Mar 2024 20:01:48 -0700 Subject: [PATCH 075/135] [Deploy] Fix scale-in operations. --- .../scheduler/comm_utils/job_utils.py | 4 ++++ .../device_replica_controller.py | 24 +++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/python/fedml/computing/scheduler/comm_utils/job_utils.py b/python/fedml/computing/scheduler/comm_utils/job_utils.py index 3c871af6db..f18543307a 100644 --- a/python/fedml/computing/scheduler/comm_utils/job_utils.py +++ b/python/fedml/computing/scheduler/comm_utils/job_utils.py @@ -214,6 +214,10 @@ def release_partial_job_gpu(self, run_id, device_id, release_gpu_ids): ComputeCacheManager.get_instance().get_gpu_cache().set_device_run_gpu_ids( device_id, run_id, remain_gpu_ids) + # set run gpu num + ComputeCacheManager.get_instance().get_gpu_cache().set_device_run_num_gpus( + device_id, run_id, len(remain_gpu_ids)) + def release_gpu_ids(self, run_id, device_id): edge_device_id = None original_run_id = None diff --git a/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py b/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py index 924109ce9b..9c43130687 100644 --- a/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py @@ -131,7 +131,7 @@ def diff_target_curr_replica_num_impl(target_replica_state, curr_replica_state): for id, curr_num in curr_replica_state.items(): if id not in target_replica_state: - diff_target_curr_replica_num[id] = {"op": "remove", "num": curr_num} + diff_target_curr_replica_num[id] = {"op": "remove", "curr_num": curr_num, "target_num": 0} return diff_target_curr_replica_num @@ -198,6 +198,8 @@ def get_curr_replica_num_state_frm_db(self): # Unpack the result_item result_device_id, _, result_payload = FedMLModelCache.get_instance().get_result_item_info(result_item) curr_state[str(result_device_id)] = curr_state.get(str(result_device_id), 0) + 1 + + logging.info(f"[Replica Controller] [endpoint {self.e_id} ] curr_replica_state from db: {curr_state}") return curr_state def get_curr_replica_version_frm_db(self): @@ -272,7 +274,10 @@ def callback_update_curr_replica_num_state(self, changed_device_id, replica_no, return if str(changed_device_id) not in self.intermediate_replica_num: - raise ValueError(f"changed_device_id {changed_device_id} is not in intermediate_replica_num") + assert op_type == ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED + + # Intermediate state is not initialized yet. Since it may derive from the database. + self.intermediate_replica_num[str(changed_device_id)] = 0 if op_type == ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED: self.intermediate_replica_num[str(changed_device_id)] += 1 @@ -284,8 +289,23 @@ def is_all_replica_num_reconciled(self): Check if all the replicas are ready. Including the number and version. """ for id, replica_no in self.intermediate_replica_num.items(): + if id not in self.target_replica_num: # Delete all replica in this device + if replica_no != 0: + return False + else: + continue if replica_no != self.target_replica_num[id]: return False + + for id, target_replica_num in self.target_replica_num.items(): + if id not in self.intermediate_replica_num or self.intermediate_replica_num[id] != target_replica_num: + return False + + logging.info(f"[Replica Controller] [endpoint {self.e_id} ] Replicas are reconciled as expected.") + logging.info(f"[Replica Controller] [endpoint {self.e_id} ] " + f"intermediate_replica_num: {self.intermediate_replica_num}") + logging.info(f"[Replica Controller] [endpoint {self.e_id} ] " + f"target_replica_num: {self.target_replica_num}") return True def get_first_chunk_devices_replica_update(self): From cfc8fccbc84e0093de747605848007765d2b61f9 Mon Sep 17 00:00:00 2001 From: Raphael Jin Date: Thu, 14 Mar 2024 20:25:39 -0400 Subject: [PATCH 076/135] [Deploy] Handle Failure Situation. --- .../model_scheduler/device_client_runner.py | 12 ------------ .../model_scheduler/device_server_runner.py | 16 +++++++--------- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py index 14b29d3c0c..7fbd557b70 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py @@ -486,12 +486,6 @@ def run_impl(self): self.mlops_metrics.client_send_exit_train_msg( run_id, self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_FAILED) - # After sending the deployment status, we should wait for the master to delete the deployment status - status_payload = self.send_deployment_status( - end_point_name, self.edge_id, model_id, model_name, model_version, inference_output_url, - ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED, inference_port=inference_port, - replica_no=rank + 1) - return False else: logging.info("finished deployment, continue to send results to master...") @@ -613,12 +607,6 @@ def run_impl(self): self.mlops_metrics.client_send_exit_train_msg( run_id, self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_FAILED) - # After sending the deployment status, we should wait for the master to delete the deployment status - status_payload = self.send_deployment_status( - end_point_name, self.edge_id, model_id, model_name, model_version, inference_output_url, - ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED, inference_port=inference_port, - replica_no=rank + 1) - return False else: logging.info("finished deployment, continue to send results to master...") diff --git a/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py b/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py index b21179237c..35071cb7b8 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py @@ -567,7 +567,11 @@ def callback_deployment_result_message(self, topic=None, payload=None): # Note: To display the result in the UI, we need to save successful deployment result to the database self.model_runner_mapping[run_id_str].deployed_replica_payload = copy.deepcopy(payload_json) else: - assert model_status == ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED + if model_status != ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED: + logging.error(f"Unsupported model status {model_status}.") + self.send_deployment_status( + end_point_id, end_point_name, payload_json["model_name"], "", + ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED) # Notify the replica number controller (self.model_runner_mapping[run_id_str]. @@ -782,14 +786,8 @@ def send_deployment_delete_request_to_edges(self, payload, model_msg_object): with open(os.path.expanduser(debug_log_path), "w") as f: f.write(str(payload)) - # Get model master node id from redis - ComputeCacheManager.get_instance().set_redis_params() - edge_device_id, model_master_device_id, model_slave_device_id = \ - ComputeCacheManager.get_instance().get_gpu_cache().get_edge_model_id_map( - model_msg_object.inference_end_point_id) - - # Remove the model_master_device_id - edge_id_list_to_delete.remove(model_master_device_id) + # Remove the model master node id from the list using index 0 + edge_id_list_to_delete = edge_id_list_to_delete[1:] logging.info("Device ids to be deleted: " + str(edge_id_list_to_delete)) From ce6a3dde9d2f1057bbe794d195489090eb357b49 Mon Sep 17 00:00:00 2001 From: Raphael Jin Date: Fri, 15 Mar 2024 15:03:44 -0400 Subject: [PATCH 077/135] [Deploy] Read the #gpu per replica from correct position; Disable MQTT Inference in default; Format Code --- .../model_scheduler/device_client_runner.py | 44 ---- .../model_scheduler/device_model_inference.py | 45 ++--- .../device_model_msg_object.py | 6 +- .../model_scheduler/device_server_runner.py | 189 ++---------------- 4 files changed, 47 insertions(+), 237 deletions(-) diff --git a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py index 7fbd557b70..f31248d01d 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py @@ -421,12 +421,6 @@ def run_impl(self): model_from_open = None self.model_is_from_open = None - # logging.info("Check if need update / removing existed container...") - # if "diff_devices" in self.request_json and str(self.edge_id) in self.request_json["diff_devices"] and \ - # self.request_json["diff_devices"][str(self.edge_id)] == ClientConstants.DEVICE_DIFF_REPLACE_OPERATION: - # # self.handle_replaced_device() - # pass - logging.info("start the model deployment...") self.check_runner_stop_event() running_model_name, inference_output_url, inference_model_version, model_metadata, model_config = \ @@ -641,44 +635,6 @@ def run_impl(self): logging.error(f"Unsupported op {op} with op num {op_num}") return False - def handle_replaced_device(self): - """ - Strategy-1: - (1) clean local records (2) find and clean current container using diff_version: {device_id: old_version} - """ - end_point_id = self.request_json["end_point_id"] - end_point_name = self.request_json["end_point_name"] - model_config = self.request_json["model_config"] - model_name = model_config["model_name"] - model_id = model_config["model_id"] - new_model_version = model_config["model_version"] - old_model_version = self.request_json["diff_version"][str(self.edge_id)] - - logging.info(f"[endpoint/device][{end_point_id}/{self.edge_id}] " - f"Start to handle replaced device {self.edge_id} to new version {new_model_version}." - f"which originally has old version {old_model_version}.") - - try: - JobRunnerUtils.get_instance().release_gpu_ids(end_point_id, self.edge_id) - - # Instead of deleting the records, need to change the job status to "UPGRADING" - FedMLClientDataInterface.get_instance().save_job_status( - end_point_id, self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_UPGRADING, - ClientConstants.MSG_MLOPS_CLIENT_STATUS_UPGRADING - ) - - FedMLModelDatabase.get_instance().delete_deployment_result_with_device_id( - end_point_id, end_point_name, model_name, self.edge_id) - - ClientConstants.remove_deployment( - end_point_name, model_name, old_model_version, - end_point_id, model_id, edge_id=self.edge_id) - except Exception as e: - # TODO: 1. Check this release action cause the resource seized by other run - # 2. If this atomic op failed, should rolling back - logging.info(f"Exception when removing deployment {traceback.format_exc()}") - pass - def construct_deployment_results(self, end_point_name, device_id, model_status, model_id, model_name, model_inference_url, model_version, inference_port, inference_engine, diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_inference.py b/python/fedml/computing/scheduler/model_scheduler/device_model_inference.py index faa16e7b4c..bf3a314ed0 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_inference.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_inference.py @@ -290,36 +290,35 @@ async def send_inference_request(idle_device, endpoint_id, inference_url, input_ logging.info(f"Use http proxy inference. return {response_ok}") return inference_response - connect_str = "@FEDML@" - random_out = sys_utils.random2(settings.ext_info, "FEDML@9999GREAT") - config_list = random_out.split(connect_str) - agent_config = dict() - agent_config["mqtt_config"] = dict() - agent_config["mqtt_config"]["BROKER_HOST"] = config_list[0] - agent_config["mqtt_config"]["BROKER_PORT"] = int(config_list[1]) - agent_config["mqtt_config"]["MQTT_USER"] = config_list[2] - agent_config["mqtt_config"]["MQTT_PWD"] = config_list[3] - agent_config["mqtt_config"]["MQTT_KEEPALIVE"] = int(config_list[4]) - mqtt_inference = FedMLMqttInference(agent_config=agent_config, run_id=endpoint_id) - response_ok = mqtt_inference.run_mqtt_health_check_with_request( - idle_device, endpoint_id, inference_url) - if response_ok: - response_ok, inference_response = mqtt_inference.run_mqtt_inference_with_request( - idle_device, endpoint_id, inference_url, input_list, output_list, inference_type=inference_type) - - if not response_ok: + if not has_public_ip: + connect_str = "@FEDML@" + random_out = sys_utils.random2(settings.ext_info, "FEDML@9999GREAT") + config_list = random_out.split(connect_str) + agent_config = dict() + agent_config["mqtt_config"] = dict() + agent_config["mqtt_config"]["BROKER_HOST"] = config_list[0] + agent_config["mqtt_config"]["BROKER_PORT"] = int(config_list[1]) + agent_config["mqtt_config"]["MQTT_USER"] = config_list[2] + agent_config["mqtt_config"]["MQTT_PWD"] = config_list[3] + agent_config["mqtt_config"]["MQTT_KEEPALIVE"] = int(config_list[4]) + mqtt_inference = FedMLMqttInference(agent_config=agent_config, run_id=endpoint_id) + response_ok = mqtt_inference.run_mqtt_health_check_with_request( + idle_device, endpoint_id, inference_url) inference_response = {"error": True, "message": "Failed to use http, http-proxy and mqtt for inference."} + if response_ok: + response_ok, inference_response = mqtt_inference.run_mqtt_inference_with_request( + idle_device, endpoint_id, inference_url, input_list, output_list, inference_type=inference_type) - logging.info(f"Use mqtt inference. return {response_ok}.") - return inference_response + logging.info(f"Use mqtt inference. return {response_ok}.") + return inference_response + return {"error": True, "message": "Failed to use http, http-proxy for inference, no response from replica."} except Exception as e: inference_response = {"error": True, - "message": f"Exception when using http, http-proxy and mqtt for inference: {traceback.format_exc()}."} + "message": f"Exception when using http, http-proxy and mqtt " + f"for inference: {traceback.format_exc()}."} logging.info("Inference Exception: {}".format(traceback.format_exc())) return inference_response - return {} - def auth_request_token(end_point_id, end_point_name, model_name, token): if token is None: diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_msg_object.py b/python/fedml/computing/scheduler/model_scheduler/device_model_msg_object.py index a6c6244108..af2087c52a 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_msg_object.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_msg_object.py @@ -102,12 +102,12 @@ def get_devices_avail_gpus(self): return self.request_json["gpu_topology"] - def get_gpu_per_replica(self): + def get_gpu_per_replica(self) -> int: """ Read gpu_per_replica from user's config yaml file. Default 1. """ - if "parameters" in self.request_json and "gpu_per_replica" in self.request_json["parameters"]: - return self.request_json["parameters"]["gpu_per_replica"] + if "gpu_per_replica" in self.request_json: + return int(self.request_json["gpu_per_replica"]) return 1 def show(self, prefix=""): diff --git a/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py b/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py index 35071cb7b8..9b3aeb2882 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py @@ -23,7 +23,6 @@ import fedml from fedml.computing.scheduler.comm_utils.run_process_utils import RunProcessUtils -from fedml.computing.scheduler.scheduler_core.compute_cache_manager import ComputeCacheManager from ..comm_utils import sys_utils from .device_server_data_interface import FedMLServerDataInterface @@ -43,7 +42,6 @@ from ..comm_utils.sys_utils import get_sys_runner_info, get_python_program from .device_model_cache import FedMLModelCache from .device_model_msg_object import FedMLModelMsgObject -#from ....serving.fedml_server import FedMLModelServingServer from ....core.mlops.mlops_utils import MLOpsUtils from ..comm_utils.constants import SchedulerConstants from .device_model_db import FedMLModelDatabase @@ -159,7 +157,10 @@ def retrieve_and_unzip_package(self, package_name, package_url): local_package_file = "{}.zip".format(os.path.join(local_package_path, package_name)) if os.path.exists(local_package_file): os.remove(local_package_file) - urllib.request.urlretrieve(package_url, filename=None, reporthook=self.package_download_progress) # do not rename + + # Download without renaming + urllib.request.urlretrieve(package_url, filename=None, reporthook=self.package_download_progress) + unzip_package_path = ServerConstants.get_model_dir() self.fedml_packages_base_dir = unzip_package_path try: @@ -299,7 +300,8 @@ def inference_run(self): def run_impl(self): run_id, end_point_name, token, user_id, user_name, device_ids, device_objs, model_config, model_name, \ model_id, model_storage_url, scale_min, scale_max, inference_engine, model_is_from_open, \ - inference_end_point_id, use_gpu, memory_size, model_version, inference_port = self.parse_model_run_params(self.request_json) + inference_end_point_id, use_gpu, memory_size, model_version, inference_port = self.parse_model_run_params( + self.request_json) logging.info("model deployment request: {}".format(self.request_json)) @@ -696,7 +698,7 @@ def send_deployment_start_request_to_edge(self, edge_id): topic_start_deployment = "model_ops/model_device/start_deployment/{}".format(str(edge_id)) logging.info("start_deployment: send topic " + topic_start_deployment + " to client...") self.client_mqtt_mgr.send_message_json(topic_start_deployment, json.dumps(self.request_json)) - + def get_ip_address(self, request_json): # OPTION 1: Use local ip ip = ServerConstants.get_local_ip() @@ -715,76 +717,7 @@ def get_ip_address(self, request_json): return ip def send_deployment_delete_request_to_edges(self, payload, model_msg_object): - if model_msg_object is None: # Called after the diff operation - if "diff_devices" not in self.request_json or self.request_json["diff_devices"] is None: - return - else: - edge_id_list_to_delete = [] - for device_id in self.request_json["diff_devices"]: - if self.request_json["diff_devices"][device_id] == ServerConstants.DEVICE_DIFF_DELETE_OPERATION: - edge_id_list_to_delete.append(device_id) - if len(edge_id_list_to_delete) == 0: - return - - try: - FedMLModelCache.get_instance().set_redis_params(self.redis_addr, self.redis_port, - self.redis_password) - - # 1. Get & Delete the endpoint device info in Redis / SQLite - device_objs = FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ - get_end_point_device_info(self.request_json["run_id"]) - - if device_objs is None: - raise Exception("The device list in local redis is None") - else: - total_device_objs_list = json.loads(device_objs) - for device_obj in total_device_objs_list: - if device_obj["id"] in edge_id_list_to_delete: - total_device_objs_list.remove(device_obj) - - FedMLModelCache.get_instance(self.redis_addr, self.redis_port).set_end_point_device_info( - self.request_json["end_point_id"], self.request_json["end_point_name"], - json.dumps(total_device_objs_list)) - - # 2 Delete the result in deployment result list in Redis / SQLite - device_result_list = FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ - get_deployment_result_list(self.request_json["end_point_id"], - self.request_json["end_point_name"], - self.request_json["model_config"]["model_name"]) - delete_device_result_list = [] - for device_result in device_result_list: - device_result_dict = json.loads(device_result) - if int(device_result_dict["cache_device_id"]) in edge_id_list_to_delete: - delete_device_result_list.append(device_result) - - for delete_item in delete_device_result_list: - FedMLModelCache.get_instance(self.redis_addr, self.redis_port).delete_deployment_result( - delete_item, self.request_json["end_point_id"], - self.request_json["end_point_name"], - self.request_json["model_config"]["model_name"] - ) - - except Exception as e: - run_id = self.request_json["run_id"] - error_log_path = f"~/.fedml/fedml-model-server/fedml/logs/error_delete_{run_id}.txt" - if not os.path.exists(os.path.dirname(os.path.expanduser(error_log_path))): - os.makedirs(os.path.dirname(os.path.expanduser(error_log_path))) - with open(os.path.expanduser(error_log_path), "w") as f: - f.write(str(self.request_json)) - f.write(str(e)) - f.write('\n') - raise e - - else: # Delete the whole endpoint - edge_id_list_to_delete = model_msg_object.device_ids - - # For Debug - if payload is not None: - debug_log_path = f"~/.fedml/fedml-model-server/fedml/logs/tmp_debug_delete_payload.txt" - if not os.path.exists(os.path.dirname(os.path.expanduser(debug_log_path))): - os.makedirs(os.path.dirname(os.path.expanduser(debug_log_path))) - with open(os.path.expanduser(debug_log_path), "w") as f: - f.write(str(payload)) + edge_id_list_to_delete = model_msg_object.device_ids # Remove the model master node id from the list using index 0 edge_id_list_to_delete = edge_id_list_to_delete[1:] @@ -934,13 +867,8 @@ def callback_start_deployment(self, topic, payload): run_id_str = str(run_id) self.running_request_json[run_id_str] = request_json - diff_devices, diff_version = self.get_diff_devices(run_id) - self.request_json["diff_devices"] = diff_devices - self.request_json["diff_version"] = diff_version self.request_json["master_node_ip"] = self.get_ip_address(self.request_json) - self.init_device_update_map() - FedMLModelCache.get_instance().set_redis_params(self.redis_addr, self.redis_port, self.redis_password) # Target status of the devices @@ -954,6 +882,8 @@ def callback_start_deployment(self, topic, payload): FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ set_end_point_token(run_id, end_point_name, model_name, token) + ServerConstants.save_runner_infos(self.args.device_id + "." + self.args.os_name, self.edge_id, run_id=run_id) + self.subscribe_slave_devices_message(request_json) # Send stage: MODEL_DEPLOYMENT_STAGE1 = "Received" @@ -973,7 +903,7 @@ def callback_start_deployment(self, topic, payload): ServerConstants.save_runner_infos(self.args.device_id + "." + self.args.os_name, self.edge_id, run_id=run_id) if self.run_as_edge_server_and_agent: - # Replica Controller is per deployment! + # Replica Controller is per deployment replica_controller = FedMLDeviceReplicaController(self.edge_id, self.request_json) logging.info(f"Start Diff Replica controller for run {run_id} on edge {self.edge_id}") @@ -1020,85 +950,6 @@ def callback_start_deployment(self, topic, payload): ServerConstants.MODEL_DEPLOYMENT_STAGE3["text"], ServerConstants.MODEL_DEPLOYMENT_STAGE3["text"]) - def get_diff_devices(self, run_id) -> (dict, dict): - ''' - {device_id(int): "op: add" | "op: delete" | "op: replace"} - "op: add" -> need to add - "op: delete" -> need to delete device - "op: replace" -> need to restart the container of the device on same port with new (same) model pkg - - {device_id(int): "old_version"} - ''' - try: - logging.info(f"Get diff devices for run {run_id}") - request_json = self.running_request_json.get(str(run_id)) - - diff_devices = {} - diff_version = {} - FedMLModelCache.get_instance().set_redis_params(self.redis_addr, self.redis_port, self.redis_password) - device_objs = FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ - get_end_point_device_info(run_id) - if device_objs is None: - for new_device_id in request_json["device_ids"]: - diff_devices[new_device_id] = ServerConstants.DEVICE_DIFF_ADD_OPERATION - else: - device_objs_dict = json.loads(device_objs) - device_ids_frm_db = [d["id"] for d in device_objs_dict] - - for exist_device_id in device_ids_frm_db: - if exist_device_id not in request_json["device_ids"]: - diff_devices[exist_device_id] = ServerConstants.DEVICE_DIFF_DELETE_OPERATION - - for new_device_id in request_json["device_ids"]: - if new_device_id not in device_ids_frm_db: - diff_devices[new_device_id] = ServerConstants.DEVICE_DIFF_ADD_OPERATION - else: - if new_device_id == self.edge_id: - continue - - old_version = self.should_update_device(request_json, new_device_id) - if old_version: - diff_devices[new_device_id] = ServerConstants.DEVICE_DIFF_REPLACE_OPERATION - diff_version[new_device_id] = old_version - else: - pass - logging.info(f"Diff devices: {diff_devices}") - except Exception as e: - error_log_path = f"~/.fedml/fedml-model-server/fedml/logs/{run_id}_error.txt" - if not os.path.exists(os.path.dirname(os.path.expanduser(error_log_path))): - os.makedirs(os.path.dirname(os.path.expanduser(error_log_path))) - with open(os.path.expanduser(error_log_path), "w") as f: - f.write(str(e)) - raise e - return diff_devices, diff_version - - def should_update_device(self, payload, new_device_id): - ''' - Query the device info in local redis, if the device info is different from the payload, - return the old model version - ''' - device_result_list = FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ - get_deployment_result_list(self.request_json["end_point_id"], - self.request_json["end_point_name"], - self.request_json["model_config"]["model_name"]) - - for device_result in device_result_list: - if device_result is None: - continue - device_result_dict = json.loads(device_result) - - if int(device_result_dict["cache_device_id"]) == new_device_id: - result_body = json.loads(device_result_dict["result"]) - if result_body["model_version"] != payload["model_config"]["model_version"]: - return result_body["model_version"] - else: - return None - return None - - def init_device_update_map(self): - # [Deprecated] Use the replica controller to manage the device update - pass - def send_first_scroll_update_msg(self): """ Replica-level rolling update. @@ -1873,7 +1724,7 @@ def setup_agent_mqtt_connection(self, service_config): "FedML_ModelServerAgent_Daemon_@" + self.user_name + "@_" + self.args.current_device_id + str(uuid.uuid4()), "flserver_agent/last_will_msg", json.dumps({"ID": self.edge_id, "status": ServerConstants.MSG_MLOPS_SERVER_STATUS_OFFLINE}) - ) + ) self.agent_config = service_config # Init local database @@ -1948,10 +1799,14 @@ def start_agent_mqtt_loop(self, should_exit_sys=True): else: print("Server tracing: {}".format(traceback.format_exc())) finally: - self.stop_agent() + self.stop_agent() + if should_exit_sys: + pass + """ + # Deprecated, will kill the process by the parent process. + time.sleep(5) + sys_utils.cleanup_all_fedml_server_login_processes( + ServerConstants.SERVER_LOGIN_PROGRAM, clean_process_group=False) + sys.exit(1) + """ - if should_exit_sys: - time.sleep(5) - sys_utils.cleanup_all_fedml_server_login_processes( - ServerConstants.SERVER_LOGIN_PROGRAM, clean_process_group=False) - sys.exit(1) From 8fb30934662a46bf18882288c6d23c3507b967c0 Mon Sep 17 00:00:00 2001 From: Raphael Jin Date: Fri, 15 Mar 2024 22:23:13 -0400 Subject: [PATCH 078/135] [Deploy] Use the model config from UI, auto-inject into mode card. --- .../model_scheduler/device_client_runner.py | 33 ++++++------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py index f31248d01d..4cf91d607e 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py @@ -18,7 +18,8 @@ from urllib.parse import urlparse, urljoin import requests -import docker + +import yaml import fedml from fedml import mlops @@ -223,18 +224,14 @@ def update_local_fedml_config(self, run_id, model_config, model_config_parameter # Load the config to memory package_conf_object = {} fedml_local_config_file = os.path.join(unzip_package_path, "fedml_model_config.yaml") - if os.path.exists(fedml_local_config_file): - package_conf_object = load_yaml_config(fedml_local_config_file) - else: - if model_config_parameters is not None: - logging.warning(f"The fedml_local_config_file {fedml_local_config_file} does not exist, will \ - create a new one with the model_config_parameters from json.") - package_conf_object = model_config_parameters - with open(fedml_local_config_file, 'w') as f: - json.dump(package_conf_object, f) - else: - logging.info(f"The fedml_local_config_file {fedml_local_config_file} does not exist,\ - and the model_config_parameters is None.") + + # Inject the config from UI to pkg yaml + package_conf_object = model_config_parameters + + # Save the config to local + with open(fedml_local_config_file, "w") as f: + yaml.dump(package_conf_object, f) + logging.info("The package_conf_object is {}".format(package_conf_object)) return unzip_package_path, model_bin_file, package_conf_object @@ -376,14 +373,6 @@ def run_impl(self): MLOpsRuntimeLog.get_instance(self.args).init_logs(log_level=logging.INFO) - # Initiate an FedMLInferenceClient object - # client_runner = FedMLClientRunner( - # self.args, edge_id=self.edge_id, run_id=self.run_id, request_json=self.request_json, - # agent_config=self.agent_config - # ) - # inference_process = Process(target=client_runner.inference_run) - # inference_process.start() - self.mlops_metrics.report_client_training_status( self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_INITIALIZING, is_from_model=True, running_json=json.dumps(self.request_json), run_id=run_id) @@ -394,8 +383,6 @@ def run_impl(self): self.check_runner_stop_event() - # TODO: Reconcile update op here. - # update local config with real time parameters from server and dynamically replace variables value logging.info("download and unzip model to local...") unzip_package_path, model_bin_file, fedml_config_object = \ From 16d731124a1d46e8e2cfeb868b3b4904290704e2 Mon Sep 17 00:00:00 2001 From: Raphael Jin Date: Sat, 16 Mar 2024 18:20:56 -0400 Subject: [PATCH 079/135] [Deploy] Use the model config from UI, auto-inject into mode card. --- .../computing/scheduler/model_scheduler/device_model_cache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py b/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py index f637ccde1d..2ba92c0b63 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_cache.py @@ -224,7 +224,7 @@ def get_result_item_info(self, result_item): result_item_json = json.loads(result_item_json) device_id = result_item_json["cache_device_id"] - replica_no = result_item_json["cache_replica_no"] + replica_no = result_item_json.get("cache_replica_no", 1) # Compatible with the old version if isinstance(result_item_json["result"], str): result_payload = json.loads(result_item_json["result"]) From 11de8b1d6ad8dc81637991e9ef1f1d9720ab72bd Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 17 Mar 2024 09:59:06 +0800 Subject: [PATCH 080/135] [DevOps] update devops files. --- python/fedml/__init__.py | 2 +- python/setup.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/python/fedml/__init__.py b/python/fedml/__init__.py index 7eaf209121..db0410196a 100644 --- a/python/fedml/__init__.py +++ b/python/fedml/__init__.py @@ -34,7 +34,7 @@ _global_training_type = None _global_comm_backend = None -__version__ = "0.8.28.dev4" +__version__ = "0.8.28.dev9" # This is the deployment environment used for different roles (RD/PM/BD/Public Developers). Potential VALUE: local, dev, test, release diff --git a/python/setup.py b/python/setup.py index e40207b966..d68c6ed370 100644 --- a/python/setup.py +++ b/python/setup.py @@ -41,7 +41,7 @@ def finalize_options(self): "wandb==0.13.2", "httpx", "attrs", - "fastapi>=0.92.0", + "fastapi", "uvicorn", "geventhttpclient>=1.4.4,<=2.0.9", "aiohttp>=3.8.1", @@ -62,7 +62,7 @@ def finalize_options(self): "py-machineid", "cachetools", "toposort", - "pydantic>=2.0", + "pydantic", "pydantic-settings", ] @@ -116,7 +116,7 @@ def finalize_options(self): setup( name="fedml", - version="0.8.28.dev4", + version="0.8.28.dev9", author="FedML Team", author_email="ch@fedml.ai", description="A research and production integrated edge-cloud library for " From d23d196ef11baca17cc6e6fde634dc78196e43f9 Mon Sep 17 00:00:00 2001 From: Raphael Jin Date: Sat, 16 Mar 2024 22:43:02 -0400 Subject: [PATCH 081/135] [Deploy] Add replica_no column if missing. --- .../computing/scheduler/model_scheduler/device_model_db.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_db.py b/python/fedml/computing/scheduler/model_scheduler/device_model_db.py index 6ee7af1cdd..579ea2ea27 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_db.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_db.py @@ -275,6 +275,11 @@ def create_table(self): except Exception as e: pass + try: + self.db_connection.execute("ALTER TABLE deployment_result_info ADD replica_no TEXT default '1';") + except Exception as e: + pass + def drop_table(self): self.open_job_db() try: From c65848ca9b6683c554049a184a9eb9595ec6d5a2 Mon Sep 17 00:00:00 2001 From: Raphael Jin Date: Sat, 16 Mar 2024 23:41:33 -0400 Subject: [PATCH 082/135] [Deploy] Add replica_no column if missing. --- .../computing/scheduler/model_scheduler/device_model_db.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_db.py b/python/fedml/computing/scheduler/model_scheduler/device_model_db.py index 6ee7af1cdd..4b3a83c2dd 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_db.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_db.py @@ -8,6 +8,7 @@ from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import declarative_base from fedml.core.common.singleton import Singleton +from sqlalchemy.sql import text Base = declarative_base() @@ -264,6 +265,12 @@ def open_job_db(self): db_session_class = sessionmaker(bind=self.db_engine) self.db_connection = db_session_class() + # Compatibility for old version + try: + self.db_connection.execute(text("ALTER TABLE deployment_result_info ADD replica_no TEXT default '1';")) + except Exception as e: + pass + def close_job_db(self): if self.db_connection is not None: self.db_connection.close() From b51d365789b92642d1e8f5b0bf30a9807fb44705 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 17 Mar 2024 14:32:39 +0800 Subject: [PATCH 083/135] [CoreEngine] close the ota. --- python/fedml/computing/scheduler/master/server_daemon.py | 2 +- python/fedml/computing/scheduler/master/server_runner.py | 4 ++-- .../scheduler/model_scheduler/device_client_runner.py | 2 +- .../scheduler/model_scheduler/device_server_runner.py | 2 +- python/fedml/computing/scheduler/slave/client_daemon.py | 2 +- python/fedml/computing/scheduler/slave/client_runner.py | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/python/fedml/computing/scheduler/master/server_daemon.py b/python/fedml/computing/scheduler/master/server_daemon.py index 9ed0cf35ef..bc02621a44 100755 --- a/python/fedml/computing/scheduler/master/server_daemon.py +++ b/python/fedml/computing/scheduler/master/server_daemon.py @@ -58,7 +58,7 @@ logging.error(f"Cleanup failed | Exception: {e}") pass - daemon_ota_upgrade(args) + # daemon_ota_upgrade(args) if platform.system() == "Windows" or \ args.role == ServerConstants.login_role_list[ServerConstants.LOGIN_MODE_CLOUD_SERVER_INDEX]: diff --git a/python/fedml/computing/scheduler/master/server_runner.py b/python/fedml/computing/scheduler/master/server_runner.py index 4906da7faf..e1080a35b7 100755 --- a/python/fedml/computing/scheduler/master/server_runner.py +++ b/python/fedml/computing/scheduler/master/server_runner.py @@ -1564,8 +1564,8 @@ def callback_start_train(self, topic=None, payload=None): f"FedMLDebug - Receive: topic ({topic}), payload ({payload})" ) - if not self.run_as_cloud_agent and not self.run_as_cloud_server: - self.ota_upgrade(payload, request_json) + # if not self.run_as_cloud_agent and not self.run_as_cloud_server: + # self.ota_upgrade(payload, request_json) # report server running status if not self.run_as_cloud_server: diff --git a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py index 4cf91d607e..36c33c3ff2 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py @@ -863,7 +863,7 @@ def callback_start_deployment(self, topic, payload): ClientConstants.FEDML_LOG_SOURCE_TYPE_MODEL_END_POINT) MLOpsRuntimeLogDaemon.get_instance(self.args).start_log_processor(run_id, self.edge_id) - self.ota_upgrade(payload, request_json) + # self.ota_upgrade(payload, request_json) # Start client with multiprocessing mode request_json["run_id"] = run_id diff --git a/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py b/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py index 9b3aeb2882..ead5ae2214 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py @@ -857,7 +857,7 @@ def callback_start_deployment(self, topic, payload): logging.info("callback_start_deployment {}".format(payload)) - self.ota_upgrade(payload, request_json) + # self.ota_upgrade(payload, request_json) run_id = inference_end_point_id self.args.run_id = run_id diff --git a/python/fedml/computing/scheduler/slave/client_daemon.py b/python/fedml/computing/scheduler/slave/client_daemon.py index 860e97c05d..e543115b4c 100755 --- a/python/fedml/computing/scheduler/slave/client_daemon.py +++ b/python/fedml/computing/scheduler/slave/client_daemon.py @@ -60,7 +60,7 @@ pass - daemon_ota_upgrade(args) + # daemon_ota_upgrade(args) if platform.system() == "Windows": login_pid = ClientConstants.exec_console_with_shell_script_list( diff --git a/python/fedml/computing/scheduler/slave/client_runner.py b/python/fedml/computing/scheduler/slave/client_runner.py index 88122f4109..8ff0500990 100755 --- a/python/fedml/computing/scheduler/slave/client_runner.py +++ b/python/fedml/computing/scheduler/slave/client_runner.py @@ -955,7 +955,7 @@ def callback_start_train(self, topic, payload): ClientConstants.save_runner_infos(self.args.device_id + "." + self.args.os_name, train_edge_id, run_id=run_id) # OTA upgrade - self.ota_upgrade(payload, request_json) + # self.ota_upgrade(payload, request_json) # Occupy GPUs scheduler_match_info = request_json.get("scheduler_match_info", {}) From 989a6ad103013a45a4b4487d8325b9152fb80188 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 17 Mar 2024 22:55:54 +0800 Subject: [PATCH 084/135] [CoreEngine] replace the direct function call with posting launching request to message queue when launching as the cloud server. --- .../scheduler/master/server_runner.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/python/fedml/computing/scheduler/master/server_runner.py b/python/fedml/computing/scheduler/master/server_runner.py index e1080a35b7..e88ab9a2f9 100755 --- a/python/fedml/computing/scheduler/master/server_runner.py +++ b/python/fedml/computing/scheduler/master/server_runner.py @@ -1521,12 +1521,6 @@ def callback_start_train(self, topic=None, payload=None): except Exception as e: pass - # get training params - if self.run_as_cloud_server: - message_bytes = payload.encode("ascii") - base64_bytes = base64.b64decode(message_bytes) - payload = base64_bytes.decode("ascii") - # [NOTES] Example Request JSON: https://fedml-inc.larksuite.com/wiki/ScnIwUif9iupbjkYS0LuBrd6sod#WjbEdhYrvogmlGxKTOGu98C6sSb request_json = json.loads(payload) is_retain = request_json.get("is_retain", False) @@ -2627,9 +2621,16 @@ def on_agent_mqtt_connected(self, mqtt_client_object): # Broadcast the first active message. self.send_agent_active_msg() + # Start the message center for listener + self.start_listener(sender_message_queue=self.message_center.get_message_queue(), + agent_config=self.agent_config) + if self.run_as_cloud_server: # Start the FedML server - self.callback_start_train(payload=self.args.runner_cmd) + message_bytes = self.args.runner_cmd.encode("ascii") + base64_bytes = base64.b64decode(message_bytes) + payload = base64_bytes.decode("ascii") + self.receive_message_json(topic_start_train, payload) # Echo results MLOpsRuntimeLog.get_instance(self.args).enable_show_log_to_stdout() @@ -2640,10 +2641,6 @@ def on_agent_mqtt_connected(self, mqtt_client_object): ) MLOpsRuntimeLog.get_instance(self.args).enable_show_log_to_stdout(enable=True) - # Start the message center for listener - self.start_listener(sender_message_queue=self.message_center.get_message_queue(), - agent_config=self.agent_config) - def on_agent_mqtt_disconnected(self, mqtt_client_object): MLOpsStatus.get_instance().set_server_agent_status( self.edge_id, ServerConstants.MSG_MLOPS_SERVER_STATUS_OFFLINE From 21125a7466c6bb445ac50c69829fd4cc2974f33b Mon Sep 17 00:00:00 2001 From: Raphael Jin Date: Mon, 18 Mar 2024 18:21:15 -0700 Subject: [PATCH 085/135] [Deploy] Expand topic to avoid mqtt crosstalk. Deprecated status topic; Clean Logs. --- .../scheduler/comm_utils/job_monitor.py | 8 +- .../model_scheduler/device_client_runner.py | 194 ++++++------------ .../device_model_deployment.py | 102 +++------ .../device_model_msg_object.py | 4 +- .../device_replica_controller.py | 6 +- .../model_scheduler/device_server_runner.py | 127 +++--------- .../core/mlops/mlops_runtime_log_daemon.py | 3 +- 7 files changed, 130 insertions(+), 314 deletions(-) diff --git a/python/fedml/computing/scheduler/comm_utils/job_monitor.py b/python/fedml/computing/scheduler/comm_utils/job_monitor.py index 28afab7b08..bd3ae7fd6c 100644 --- a/python/fedml/computing/scheduler/comm_utils/job_monitor.py +++ b/python/fedml/computing/scheduler/comm_utils/job_monitor.py @@ -274,7 +274,6 @@ def monitor_slave_endpoint_status(self): model_id = model_config.get("model_id", None) endpoint_name = endpoint_json.get("end_point_name", None) device_ids = endpoint_json.get("device_ids", []) - logging.info(f"Check endpoint status for {job.job_id}:{job.edge_id}.") if model_name is None: continue @@ -289,6 +288,7 @@ def monitor_slave_endpoint_status(self): # Check the container (replica) ready probe # TODO: Parallel this check rank = -1 + for deployment_result in deployment_result_list: rank += 1 is_endpoint_ready = self._check_and_reset_endpoint_status( @@ -308,6 +308,11 @@ def monitor_slave_endpoint_status(self): started, inference_port = ContainerUtils.get_instance().start_container( endpoint_container_name) else: + logging.info( + f"======================================" + f"Check endpoint status failed for endpoint {job.job_id} " + f"on device:{job.edge_id} with replica_no:{rank+1}." + f"======================================") # Restart the container if the endpoint is not ready # send unavailable status to the master agent # TODO: Check the callback from the master agent @@ -501,7 +506,6 @@ def _check_and_reset_endpoint_status( def is_inference_ready(self, inference_url, timeout=None, device_id=None, endpoint_id=None, use_mqtt=False): response_ok = asyncio.run(FedMLHttpInference.is_inference_ready(inference_url, timeout=timeout)) if response_ok: - print("Use http health check.") return response_ok if response_ok is None: diff --git a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py index 36c33c3ff2..b3732b6a8d 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py @@ -114,7 +114,6 @@ def __init__(self, args, edge_id=0, request_json=None, agent_config=None, run_id self.redis_addr = "local" self.redis_port = "6379" self.redis_password = "fedml_default" - self.model_is_from_open = False self.model_runner_mapping = dict() self.ntp_offset = MLOpsUtils.get_ntp_offset() @@ -197,7 +196,7 @@ def package_download_progress(self, count, blksize, filesize): progress_int = int(progress) downloaded_kb = format(downloaded / 1024, '.2f') - # since this hook funtion is stateless, we need a state to avoid printing progress repeatly + # since this hook function is stateless, we need a state to avoid printing progress repeatedly if count == 0: self.prev_download_progress = 0 if progress_int != self.prev_download_progress and progress_int % 5 == 0: @@ -216,10 +215,7 @@ def update_local_fedml_config(self, run_id, model_config, model_config_parameter inference_end_point_id = run_id # Retrieve model package or model binary file. - if self.model_is_from_open: - unzip_package_path, model_bin_file = self.retrieve_binary_model_file(model_name, model_storage_url) - else: - unzip_package_path, model_bin_file = self.retrieve_and_unzip_package(model_name, model_storage_url) + unzip_package_path, model_bin_file = self.retrieve_and_unzip_package(model_name, model_storage_url) # Load the config to memory package_conf_object = {} @@ -269,34 +265,40 @@ def run(self, process_event, completed_event): if not self.run_impl(): logging.info( - f"[endpoint/device][{run_id}/{self.edge_id}] Release gpu resource when the worker deployment returned false.") + f"[endpoint/device][{run_id}/{self.edge_id}] " + f"Failed to run the model deployment. run_impl return False.") self.release_gpu_ids(run_id) except RunnerError: - logging.info("Runner stopped.") - logging.info( - f"[endpoint/device][{run_id}/{self.edge_id}] Release gpu resource when the worker deployment stopped.") + logging.error( + f"[endpoint/device][{run_id}/{self.edge_id}] " + f"Failed due to RunnerError {traceback.format_exc()}") self.release_gpu_ids(run_id) + self.reset_devices_status(self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_KILLED) MLOpsRuntimeLogDaemon.get_instance(self.args).stop_log_processor(run_id, self.edge_id) except RunnerCompletedError: - logging.info( - f"[endpoint/device][{run_id}/{self.edge_id}] Release gpu resource when the worker deployment completed.") + logging.error( + f"[endpoint/device][{run_id}/{self.edge_id}] " + f"Failed due to RunnerCompletedError {traceback.format_exc()}") self.release_gpu_ids(run_id) - logging.info("Runner completed.") + MLOpsRuntimeLogDaemon.get_instance(self.args).stop_log_processor(run_id, self.edge_id) except Exception as e: - logging.error("Runner exits with exceptions. {}".format(traceback.format_exc())) + logging.error( + f"[endpoint/device][{run_id}/{self.edge_id}] " + f"Failed due to exception {traceback.format_exc()}") + self.cleanup_run_when_starting_failed() self.mlops_metrics.client_send_exit_train_msg( run_id, self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_FAILED) - logging.info( - f"[endpoint/device][{run_id}/{self.edge_id}] Release gpu resource when the worker deployment occurred exceptions.") + self.release_gpu_ids(run_id) + MLOpsRuntimeLogDaemon.get_instance(self.args).stop_log_processor(run_id, self.edge_id) time.sleep(2) sys.exit(1) finally: - logging.info("Release resources.") + logging.info("[Worker] Release resources after deployment.") MLOpsRuntimeLogDaemon.get_instance(self.args).stop_log_processor(run_id, self.edge_id) if self.mlops_metrics is not None: self.mlops_metrics.stop_sys_perf() @@ -315,68 +317,35 @@ def check_runner_stop_event(self): logging.info("Received completed event.") raise RunnerCompletedError("Runner completed") - def inference_run(self): - # run_id, end_point_name, token, user_id, user_name, device_ids, device_objs, model_config, model_name, \ - # model_id, model_storage_url, scale_min, scale_max, inference_engine, model_is_from_open, \ - # inference_end_point_id, use_gpu, memory_size, model_version = self.parse_model_run_params(self.request_json) - # - # inference_client = FedMLModelServingClient(self.args, - # end_point_name, - # model_name, - # model_version, - # inference_request=self.request_json) - # inference_client.run() - pass - def run_impl(self): + # Get deployment params run_id = self.request_json["end_point_id"] end_point_name = self.request_json["end_point_name"] - token = self.request_json["token"] - user_id = self.request_json["user_id"] - user_name = self.request_json["user_name"] device_ids = self.request_json["device_ids"] - device_objs = self.request_json["device_objs"] master_ip = self.request_json["master_node_ip"] - model_config = self.request_json["model_config"] model_name = model_config["model_name"] model_id = model_config["model_id"] model_version = model_config["model_version"] - model_storage_url = model_config["model_storage_url"] - scale_min = model_config.get("instance_scale_min", 0) - scale_max = model_config.get("instance_scale_max", 0) model_config_parameters = self.request_json["parameters"] - inference_port = model_config_parameters.get("worker_internal_port", ClientConstants.MODEL_INFERENCE_DEFAULT_PORT) inference_port_external = model_config_parameters.get("worker_external_port", inference_port) - - if "using_triton" in model_config_parameters and model_config_parameters["using_triton"]: - inference_engine = ClientConstants.INFERENCE_ENGINE_TYPE_INT_TRITON - else: - inference_engine = ClientConstants.INFERENCE_ENGINE_TYPE_INT_DEFAULT - - logging.info("[Critical] The inference_engine is: {}".format(inference_engine)) - - self.model_is_from_open = True if model_config.get("is_from_open", 0) == 1 else False - if self.model_is_from_open: - model_net_url = model_config["model_net_url"] + inference_engine = model_config_parameters.get("inference_engine", + ClientConstants.INFERENCE_ENGINE_TYPE_INT_DEFAULT) inference_end_point_id = run_id - use_gpu = "gpu" # TODO: Get GPU from device infos - memory_size = "4096m" # TODO: Get Memory size for each instance self.mlops_metrics.report_sys_perf(self.args, self.agent_config["mqtt_config"], run_id=run_id) + MLOpsRuntimeLog.get_instance(self.args).init_logs(log_level=logging.INFO) - self.check_runner_stop_event() - - logging.info("model deployment request: {}".format(self.request_json)) + logging.info("[Worker] Received model deployment request from master.") - MLOpsRuntimeLog.get_instance(self.args).init_logs(log_level=logging.INFO) + self.check_runner_stop_event() + # Report the deployment status to mlops self.mlops_metrics.report_client_training_status( self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_INITIALIZING, is_from_model=True, running_json=json.dumps(self.request_json), run_id=run_id) - self.mlops_metrics.report_client_training_status( self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_RUNNING, is_from_model=True, run_id=run_id) @@ -384,31 +353,26 @@ def run_impl(self): self.check_runner_stop_event() # update local config with real time parameters from server and dynamically replace variables value - logging.info("download and unzip model to local...") + logging.info("Download and unzip model to local...") unzip_package_path, model_bin_file, fedml_config_object = \ self.update_local_fedml_config(run_id, model_config, model_config_parameters) if unzip_package_path is None or fedml_config_object is None: - logging.info("failed to update local fedml config.") + logging.info("Failed to update local fedml config.") self.check_runner_stop_event() self.cleanup_run_when_starting_failed() self.mlops_metrics.client_send_exit_train_msg(run_id, self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_FAILED) return False - logging.info("check downloaded packages...") if not os.path.exists(unzip_package_path): - logging.info("failed to unzip file.") + logging.info("Failed to unzip file.") self.check_runner_stop_event() self.cleanup_run_when_starting_failed() self.mlops_metrics.client_send_exit_train_msg(run_id, self.edge_id, ClientConstants.MSG_MLOPS_CLIENT_STATUS_FAILED) return False - # download model net and load into the torch model - model_from_open = None - self.model_is_from_open = None - - logging.info("start the model deployment...") + logging.info("[Worker] Start the model deployment...") self.check_runner_stop_event() running_model_name, inference_output_url, inference_model_version, model_metadata, model_config = \ "", "", model_version, {}, {} @@ -422,9 +386,11 @@ def run_impl(self): replica_rank_to_update, op = self.replica_handler.reconcile_replica_version() if not op: - logging.info("No need to reconcile.") + logging.info("[Worker] No need to reconcile.") return True + logging.info(f"[Worker] Reconcile replica with op {op} and op num {op_num}." + f"======================================") if op == "add": worker_ip = self.get_ip_address(self.request_json) for rank in range(prev_rank+1, prev_rank+1+op_num): @@ -432,27 +398,19 @@ def run_impl(self): try: running_model_name, inference_output_url, inference_model_version, model_metadata, model_config = \ start_deployment( - inference_end_point_id, end_point_name, model_id, model_version, - unzip_package_path, model_bin_file, model_name, inference_engine, - ClientConstants.INFERENCE_HTTP_PORT, - ClientConstants.INFERENCE_GRPC_PORT, - ClientConstants.INFERENCE_METRIC_PORT, - use_gpu, memory_size, - ClientConstants.INFERENCE_CONVERTOR_IMAGE, - ClientConstants.INFERENCE_SERVER_IMAGE, - worker_ip, - self.model_is_from_open, model_config_parameters, - model_from_open, - token, - master_ip, self.edge_id, master_device_id=device_ids[0], replica_rank=rank, + end_point_id=inference_end_point_id, end_point_name=end_point_name, model_id=model_id, + model_version=model_version, model_storage_local_path=unzip_package_path, + inference_model_name=model_name, inference_engine=inference_engine, + infer_host=worker_ip, master_ip=master_ip, edge_id=self.edge_id, + master_device_id=device_ids[0], replica_rank=rank, gpu_per_replica=int(self.replica_handler.gpu_per_replica) ) except Exception as e: inference_output_url = "" - logging.error(f"Exception at deployment: {traceback.format_exc()}") + logging.error(f"[Worker] Exception at deployment: {traceback.format_exc()}") if inference_output_url == "": - logging.error("failed to deploy the model...") + logging.error("[Worker] Failed to deploy the model.") result_payload = self.send_deployment_results( end_point_name, self.edge_id, ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED, @@ -469,13 +427,14 @@ def run_impl(self): return False else: - logging.info("finished deployment, continue to send results to master...") + logging.info("Finished deployment, continue to send results to master...") result_payload = self.send_deployment_results( end_point_name, self.edge_id, ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED, model_id, model_name, inference_output_url, model_version, inference_port_external, inference_engine, model_metadata, model_config, replica_no=rank + 1) - if inference_port_external != inference_port: # Save internal port to local db + if inference_port_external != inference_port: + # Save internal port to local db logging.info("inference_port_external {} != inference_port {}".format( inference_port_external, inference_port)) result_payload = self.construct_deployment_results( @@ -531,7 +490,7 @@ def run_impl(self): # Update is combine of delete and add worker_ip = self.get_ip_address(self.request_json) for rank in replica_rank_to_update: - # Delete the container + # Delete a replica (container) self.replica_handler.remove_replica(rank) FedMLModelCache.get_instance().set_redis_params() @@ -546,26 +505,20 @@ def run_impl(self): FedMLModelDatabase.get_instance().delete_deployment_result_with_device_id_and_rank( run_id, end_point_name, model_name, self.edge_id, rank) + logging.info(f"Delete replica with no {rank + 1} successfully.") time.sleep(1) - # Add the container + # Add a replica (container) # TODO: Reduce the duplicated code + logging.info(f"Start to deploy the model with replica no {rank + 1} ...") try: running_model_name, inference_output_url, inference_model_version, model_metadata, model_config = \ start_deployment( - inference_end_point_id, end_point_name, model_id, model_version, - unzip_package_path, model_bin_file, model_name, inference_engine, - ClientConstants.INFERENCE_HTTP_PORT, - ClientConstants.INFERENCE_GRPC_PORT, - ClientConstants.INFERENCE_METRIC_PORT, - use_gpu, memory_size, - ClientConstants.INFERENCE_CONVERTOR_IMAGE, - ClientConstants.INFERENCE_SERVER_IMAGE, - worker_ip, - self.model_is_from_open, model_config_parameters, - model_from_open, - token, - master_ip, self.edge_id, master_device_id=device_ids[0], replica_rank=rank, + end_point_id=inference_end_point_id, end_point_name=end_point_name, model_id=model_id, + model_version=model_version, model_storage_local_path=unzip_package_path, + inference_model_name=model_name, inference_engine=inference_engine, + infer_host=worker_ip, master_ip=master_ip, edge_id=self.edge_id, + master_device_id=device_ids[0], replica_rank=rank, gpu_per_replica=int(self.replica_handler.gpu_per_replica) ) except Exception as e: @@ -590,7 +543,7 @@ def run_impl(self): return False else: - logging.info("finished deployment, continue to send results to master...") + logging.info("Finished deployment, continue to send results to master...") result_payload = self.send_deployment_results( end_point_name, self.edge_id, ClientConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED, model_id, model_name, inference_output_url, model_version, inference_port_external, @@ -659,7 +612,9 @@ def send_deployment_results(self, end_point_name, device_id, model_status, model_id, model_name, model_inference_url, model_version, inference_port, inference_engine, model_metadata, model_config, replica_no=1): - deployment_results_topic = "model_device/model_device/return_deployment_result/{}".format(device_id) + deployment_results_topic = "model_device/model_device/return_deployment_result/{}/{}".format( + self.run_id, device_id) + deployment_results_payload = self.construct_deployment_results( end_point_name, device_id, model_status, model_id, model_name, model_inference_url, @@ -677,18 +632,8 @@ def send_deployment_status(self, end_point_name, device_id, inference_port=ClientConstants.MODEL_INFERENCE_DEFAULT_PORT, replica_no=1, # start from 1 ): - deployment_status_topic = "model_device/model_device/return_deployment_status/{}".format(device_id) - deployment_status_payload = self.construct_deployment_status( - end_point_name, device_id, - model_id, model_name, model_version, - model_inference_url, model_status, - inference_port=inference_port, - replica_no=replica_no) - - logging.info("[client] send_deployment_status: topic {}, payload {}.".format(deployment_status_topic, - deployment_status_payload)) - self.client_mqtt_mgr.send_message_json(deployment_status_topic, json.dumps(deployment_status_payload)) - return deployment_status_payload + # Deprecated + pass def reset_devices_status(self, edge_id, status): self.mlops_metrics.run_id = self.run_id @@ -827,26 +772,9 @@ def ota_upgrade(self, payload, request_json): raise Exception("Restarting after upgraded...") def callback_start_deployment(self, topic, payload): - """ - topic: model_ops/model_device/start_deployment/model-agent-device-id - payload: {"model_name": "image-model", "model_storage_url":"s3-url", - "instance_scale_min":1, "instance_scale_max":3, "inference_engine":"onnx (or tensorrt)"} - """ - # get deployment params + # Get deployment params request_json = json.loads(payload) run_id = request_json["end_point_id"] - token = request_json["token"] - user_id = request_json["user_id"] - user_name = request_json["user_name"] - device_ids = request_json["device_ids"] - device_objs = request_json["device_objs"] - - model_config = request_json["model_config"] - model_name = model_config["model_name"] - model_storage_url = model_config["model_storage_url"] - scale_min = model_config.get("instance_scale_min", 0) - scale_max = model_config.get("instance_scale_max", 0) - inference_engine = model_config.get("inference_engine", 0) inference_end_point_id = run_id try: @@ -882,7 +810,7 @@ def callback_start_deployment(self, topic, payload): client_runner.run_process_completed_event = self.run_process_completed_event_map[run_id_str] self.model_runner_mapping[run_id_str] = client_runner - # Replica Handler is per deployment! + # Replica Handler will be init for every deployment replica_handler = FedMLDeviceReplicaHandler(self.edge_id, self.request_json) client_runner.replica_handler = replica_handler @@ -890,7 +818,7 @@ def callback_start_deployment(self, topic, payload): self.run_process_map[run_id_str] = Process(target=client_runner.run, args=( self.run_process_event_map[run_id_str], self.run_process_completed_event_map[run_id_str] )) - # client_runner.run() + self.run_process_map[run_id_str].start() ClientConstants.save_run_process(run_id, self.run_process_map[run_id_str].pid) ClientConstants.save_runner_infos(self.args.device_id + "." + self.args.os_name, self.edge_id, run_id=run_id) diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_deployment.py b/python/fedml/computing/scheduler/model_scheduler/device_model_deployment.py index 7477795e1c..3acd908fe6 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_deployment.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_deployment.py @@ -66,36 +66,25 @@ def request_gpu_ids_on_deployment(edge_id, end_point_id, num_gpus=None, master_d def start_deployment(end_point_id, end_point_name, model_id, model_version, - model_storage_local_path, model_bin_file, inference_model_name, inference_engine, - inference_http_port, inference_grpc_port, inference_metric_port, - inference_use_gpu, inference_memory_size, - inference_convertor_image, inference_server_image, - infer_host, model_is_from_open, model_params, - model_from_open, token, master_ip, edge_id, master_device_id=None, replica_rank=0, + model_storage_local_path, inference_model_name, inference_engine, + infer_host, master_ip, edge_id, master_device_id=None, replica_rank=0, gpu_per_replica=1): - logging.info("Model deployment is starting...") + logging.info("[Worker] Model deployment is starting...") - sudo_prefix = "sudo " - sys_name = platform.system() - if sys_name == "Darwin": - sudo_prefix = "" - num_gpus = gpu_per_replica # Real gpu per replica (container) + # Real gpu per replica (container-level) + num_gpus = gpu_per_replica gpu_ids, gpu_attach_cmd = None, "" running_model_name = ClientConstants.get_running_model_name( end_point_name, inference_model_name, model_version, end_point_id, model_id, edge_id=edge_id) - if model_is_from_open: - logging.error("The model is directly export from open, currently do not convert the model to servable format.") - return "", "", None, None, None - # Parse the model config file and get the necessary information for the deployment model_config_path = os.path.join(model_storage_local_path, "fedml_model_config.yaml") with open(model_config_path, 'r') as file: config = yaml.safe_load(file) + # Resource related use_gpu = config.get('use_gpu', True) - in_gpu_ids = config.get('gpu_ids', gpu_ids) num_gpus_frm_yml = config.get('num_gpus', None) if not use_gpu: num_gpus = 0 @@ -193,7 +182,6 @@ def start_deployment(end_point_id, end_point_name, model_id, model_version, end_point_id, end_point_name, inference_model_name, edge_id, replica_rank+1, gpu_ids) logging.info("GPU ids allocated: {}".format(gpu_ids)) - logging.info("move converted model to serving dir for inference...") model_serving_dir = ClientConstants.get_model_serving_dir() if not os.path.exists(model_serving_dir): os.makedirs(model_serving_dir, exist_ok=True) @@ -262,10 +250,9 @@ def start_deployment(end_point_id, end_point_name, model_id, model_version, logging.info(f"device_requests: {device_requests}") # Pull the inference image - logging.info(f"Start pulling the inference image {inference_image_name}..., may take a few minutes...") + logging.info(f"Start pulling the inference image {inference_image_name}... with policy {image_pull_policy}") ContainerUtils.get_instance().pull_image_with_policy(image_pull_policy, inference_image_name) - logging.info("Start creating the inference container...") volumns = [] binds = {} environment = {} @@ -273,7 +260,7 @@ def start_deployment(end_point_id, end_point_name, model_id, model_version, # data_cache_dir mounting assert type(data_cache_dir_input) == dict or type(data_cache_dir_input) == str if type(data_cache_dir_input) == str: - # In this case, we mount to the same folder, if has ~, we replace it with /home/fedml + # In this case, we mount to the same folder, if it has ~, we replace it with /home/fedml src_data_cache_dir, dst_data_cache_dir = "", "" if data_cache_dir_input != "": if data_cache_dir_input[0] == "~": @@ -382,7 +369,7 @@ def start_deployment(end_point_id, end_point_name, model_id, model_version, raise Exception("Failed to get the port allocation") time.sleep(3) - # Logging the info from the container + # Logging the info from the container when starting log_deployment_result(end_point_id, model_id, default_server_container_name, ClientConstants.CMD_TYPE_RUN_DEFAULT_SERVER, inference_model_name, inference_engine, inference_http_port, inference_type, @@ -390,7 +377,7 @@ def start_deployment(end_point_id, end_point_name, model_id, model_version, request_input_example=request_input_example, infer_host=infer_host, enable_custom_image=enable_custom_image) - # Check if the inference server is ready + # Return the running model name and the inference output url inference_output_url, running_model_version, ret_model_metadata, ret_model_config = \ get_model_info(inference_model_name, inference_engine, inference_http_port, infer_host, False, inference_type, request_input_example=request_input_example, @@ -399,8 +386,10 @@ def start_deployment(end_point_id, end_point_name, model_id, model_version, if inference_output_url == "": return running_model_name, "", None, None, None + # Successfully get the result from the container model_metadata = ret_model_metadata - logging.info(model_metadata) + logging.info(f"[Worker][Replica{replica_rank}] Model deployment is successful with inference_output_url: " + f"{inference_output_url}, model_metadata: {model_metadata}, model_config: {ret_model_config}") return running_model_name, inference_output_url, model_version, model_metadata, ret_model_config @@ -438,41 +427,7 @@ def build_inference_req(end_point_name, model_name, token, in_model_metadata): def should_exit_logs(end_point_id, model_id, cmd_type, model_name, inference_engine, inference_port, inference_type="default", request_input_example=None, infer_host="127.0.0.1", enable_custom_image=False): - sudo_prefix = "sudo " - sys_name = platform.system() - if sys_name == "Darwin": - sudo_prefix = "" - - if cmd_type == ClientConstants.CMD_TYPE_CONVERT_MODEL: - convert_model_container_name = "{}_{}_{}".format(ClientConstants.FEDML_CONVERT_MODEL_CONTAINER_NAME_PREFIX, - str(end_point_id), - str(model_id)) - docker_ps_cmd = "{}docker ps -a;exit".format(sudo_prefix, convert_model_container_name) - docker_ps_process = ClientConstants.exec_console_with_script(docker_ps_cmd, - should_capture_stdout=True, - should_capture_stderr=True) - ret_code, out, err = ClientConstants.get_console_pipe_out_err_results(docker_ps_process) - if out is not None: - out_str = sys_utils.decode_our_err_result(out) - if str(out_str).find(convert_model_container_name) == -1: - return True - else: - return False - else: - return True - elif cmd_type == ClientConstants.CMD_TYPE_RUN_TRITON_SERVER: - try: - inference_output_url, model_version, model_metadata, model_config = \ - get_model_info(model_name, inference_engine, inference_port, inference_type=inference_type) - logging.info("Log test for deploying model successfully, inference url: {}, " - "model metadata: {}, model config: {}". - format(inference_output_url, model_metadata, model_config)) - if inference_output_url != "": - return True - except Exception as e: - pass - return False - elif cmd_type == ClientConstants.CMD_TYPE_RUN_DEFAULT_SERVER: + if cmd_type == ClientConstants.CMD_TYPE_RUN_DEFAULT_SERVER: # TODO: Exited Quickly if the container is Exited or Removed # If the container has exited, return True, means we should exit the logs # container_name = "{}".format(ClientConstants.FEDML_DEFAULT_SERVER_CONTAINER_NAME_PREFIX) + "__" + \ @@ -482,13 +437,17 @@ def should_exit_logs(end_point_id, model_id, cmd_type, model_name, inference_eng get_model_info(model_name, inference_engine, inference_port, infer_host, inference_type=inference_type, request_input_example=request_input_example, enable_custom_image=enable_custom_image) - logging.info("Log test for deploying model successfully, inference url: {}, " - "model metadata: {}, model config: {}". - format(inference_output_url, model_metadata, model_config)) if inference_output_url != "": + logging.info("Log test for deploying model successfully, inference url: {}, " + "model metadata: {}, model config: {}". + format(inference_output_url, model_metadata, model_config)) return True except Exception as e: pass + + return False + else: + logging.error("Unknown cmd type: {}".format(cmd_type)) return False @@ -500,8 +459,6 @@ def log_deployment_result(end_point_id, model_id, cmd_container_name, cmd_type, enable_custom_image=False): deploy_attempt = 0 last_log_time = datetime.datetime.now() - last_out_logs = "" - last_err_logs = "" while True: if not ClientConstants.is_running_on_k8s(): @@ -524,6 +481,7 @@ def log_deployment_result(end_point_id, model_id, cmd_container_name, cmd_type, break if container_obj is not None: + out_logs, err_logs = None, None try: out_logs = container_obj.logs(stdout=True, stderr=False, stream=False, follow=False, since=last_log_time) @@ -537,22 +495,15 @@ def log_deployment_result(end_point_id, model_id, cmd_container_name, cmd_type, if err_logs is not None: err_logs = sys_utils.decode_our_err_result(err_logs) - err_logs = f"logs from docker: {format(err_logs)}" - if err_logs.startswith("ERROR:") or err_logs.startswith("CRITICAL:"): - logging.error(err_logs) - elif err_logs.startswith("WARNING:"): - logging.warning(err_logs) - elif err_logs.startswith("DEBUG:"): - logging.debug(err_logs) - else: - logging.info(err_logs) + logging.error(f"Error logs from docker: {format(err_logs)}") if out_logs is not None: out_logs = sys_utils.decode_our_err_result(out_logs) logging.info(f"Logs from docker: {format(out_logs)}") if container_obj.status == "exited": - logging.info("Container {} has exited".format(cmd_container_name)) + logging.info("Container {} has exited, automatically remove it".format(cmd_container_name)) + client.api.remove_container(container_obj.id, v=True, force=True) break # should_exit_logs will ping the inference container @@ -632,8 +583,6 @@ def get_model_info(model_name, inference_engine, inference_http_port, infer_host return "", "", {}, {} local_infer_url = "{}:{}".format(infer_host, inference_http_port) - logging.info(f"The infer_url_host is {infer_host}") - logging.info(f"Local infer url: {local_infer_url}.") if is_hg_model: inference_model_name = "{}_{}_inference".format(model_name, str(inference_engine)) @@ -644,7 +593,6 @@ def get_model_info(model_name, inference_engine, inference_http_port, infer_host infer_host, inference_http_port, inference_model_name, local_infer_url, inference_type, model_version="", request_input_example=request_input_example) - logging.info(f"The res is {response_from_client_container}") return response_from_client_container diff --git a/python/fedml/computing/scheduler/model_scheduler/device_model_msg_object.py b/python/fedml/computing/scheduler/model_scheduler/device_model_msg_object.py index af2087c52a..6ec05f64ed 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_model_msg_object.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_model_msg_object.py @@ -97,8 +97,8 @@ def get_devices_avail_gpus(self): res[id] = int(self.scale_min) return res - logging.info(f"[Replica Controller] [endpoint {self.run_id}] " - f"devices_avail_gpus: {self.request_json['gpu_topology']}") + logging.info(f"[Replica Controller]" + f"Target gpu_topology from MLOps: {self.request_json['gpu_topology']}") return self.request_json["gpu_topology"] diff --git a/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py b/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py index 9c43130687..06ef3ed8e9 100644 --- a/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py @@ -76,11 +76,9 @@ def init_id_replica_num(self): return id_replica_num def diff_target_curr_replica_num(self): - logging.info(f"[Replica Controller] [endpoint {self.e_id} ]target_replica_state: {self.target_replica_num}") - logging.info(f"[Replica Controller] [endpoint {self.e_id} ]curr_replica_state: {self.curr_replica_num}") diff = self.diff_target_curr_replica_num_impl(self.target_replica_num, self.curr_replica_num) logging.info( - f"[Replica Controller] [endpoint {self.e_id} ]diff_target_curr_replica_num: {diff}") + f"[Replica Controller] [endpoint {self.e_id} ] <<<<< diff_target_curr_replica_num: {diff} >>>>>") return diff def diff_target_curr_replica_version(self): @@ -93,7 +91,7 @@ def diff_target_curr_replica_version(self): self.target_replica_version, self.curr_replica_version) logging.info( - f"[Replica Controller] [endpoint {self.e_id} ]diff_target_curr_replica_version: {diff}") + f"[Replica Controller] [endpoint {self.e_id} ] <<<<< diff_target_curr_replica_version: {diff} >>>>>") return num_diff, diff @staticmethod diff --git a/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py b/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py index ead5ae2214..b3051b6279 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py @@ -245,7 +245,7 @@ def run(self, process_event, completed_event): time.sleep(3) sys.exit(1) finally: - logging.info("Release resources.") + logging.info("[Master] Deployment finished, release resources.") MLOpsRuntimeLogDaemon.get_instance(self.args).stop_log_processor(run_id, self.edge_id) if self.mlops_metrics is not None: self.mlops_metrics.stop_sys_perf() @@ -303,17 +303,6 @@ def run_impl(self): inference_end_point_id, use_gpu, memory_size, model_version, inference_port = self.parse_model_run_params( self.request_json) - logging.info("model deployment request: {}".format(self.request_json)) - - # Initiate an FedMLInferenceServer object which the request will be forwarded to - # server_runner = FedMLServerRunner( - # self.args, run_id=self.run_id, request_json=self.request_json, agent_config=self.agent_config - # ) - # inference_process = Process(target=server_runner.inference_run) - # inference_process.start() - - logging.info("send deployment stages...") - self.mlops_metrics.report_sys_perf(self.args, self.agent_config["mqtt_config"], run_id=run_id) self.check_runner_stop_event() @@ -328,8 +317,7 @@ def run_impl(self): self.args.run_id = self.run_id MLOpsRuntimeLog.get_instance(self.args).init_logs(log_level=logging.INFO) - # report server running status - logging.info("report deployment status...") + # Report server running status self.check_runner_stop_event() self.mlops_metrics.report_server_training_status( run_id, ServerConstants.MSG_MLOPS_SERVER_STATUS_STARTING, @@ -338,31 +326,31 @@ def run_impl(self): model_name, "", ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYING) - # start unified inference server + # Start unified inference gateway if it has not started self.start_device_inference_gateway( run_id, end_point_name, model_id, model_name, model_version, inference_port=inference_port) - # start inference monitor server + # (re)Start inference monitor server self.stop_device_inference_monitor(run_id, end_point_name, model_id, model_name, model_version) self.start_device_inference_monitor(run_id, end_point_name, model_id, model_name, model_version) - # Changed the status to "IDLE" + # Changed the master's status to "IDLE" self.mlops_metrics.broadcast_server_training_status( run_id, ServerConstants.MSG_MLOPS_SERVER_STATUS_FINISHED, is_from_model=True, edge_id=self.edge_id) - # forward deployment request to slave devices - logging.info("send the model inference request to slave devices...") + # Forward deployment request to slave devices self.check_runner_stop_event() - # handle "op:add" && "op:remove" + # Handle "op:add" && "op:remove" devices_sent_add_or_remove_msg = self.send_deployment_start_request_to_edges() - # handle "op:update" + # Handle "op:update" devices_sent_update_remove_msg = self.send_first_scroll_update_msg() if len(devices_sent_add_or_remove_msg) == 0 and len(devices_sent_update_remove_msg) == 0: - # No device is added or removed, and no device is updated or removed + # No device is added, updated or removed + logging.info("No device is added, updated or removed. No action needed for reconciliation.") ip = self.get_ip_address(self.request_json) master_port = os.getenv("FEDML_MASTER_PORT", None) if master_port is not None: @@ -381,7 +369,10 @@ def run_impl(self): ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_DEPLOYED) return + logging.info("Start waiting for result callback from workers ...") + while True: + # Wait for all devices to finish the add / delete / update operation self.check_runner_stop_event() time.sleep(3) @@ -696,7 +687,7 @@ def send_deployment_start_request_to_edges(self): def send_deployment_start_request_to_edge(self, edge_id): topic_start_deployment = "model_ops/model_device/start_deployment/{}".format(str(edge_id)) - logging.info("start_deployment: send topic " + topic_start_deployment + " to client...") + logging.info("start_deployment: send topic " + topic_start_deployment + f" to client {edge_id}...") self.client_mqtt_mgr.send_message_json(topic_start_deployment, json.dumps(self.request_json)) def get_ip_address(self, request_json): @@ -708,7 +699,6 @@ def get_ip_address(self, request_json): ServerConstants.AUTO_DETECT_PUBLIC_IP in request_json["parameters"] and \ request_json["parameters"][ServerConstants.AUTO_DETECT_PUBLIC_IP]: ip = ServerConstants.get_public_ip() - logging.info("Auto detect public ip for master: " + ip) # OPTION 3: Use user indicated ip if self.infer_host is not None and self.infer_host != "127.0.0.1" and self.infer_host != "localhost": @@ -773,62 +763,12 @@ def ota_upgrade(self, payload, request_json): raise Exception("Restarting after upgraded...") def callback_start_deployment(self, topic, payload): - """ - topic: model_ops/model_device/start_deployment/model-agent-device-id - payload: - { - "timestamp": 1671440005119, - "end_point_id": 4325, - "token": "FCpWU", - "state": "STARTING", - "user_id": "105", - "user_name": "alex.liang2", - "device_ids": [ - 693 - ], - "device_objs": [ - { - "device_id": "0xT3630FW2YM@MacOS.Edge.Device", - "os_type": "MacOS", - "id": 693, - "ip": "1.1.1.1", - "memory": 1024, - "cpu": "1.7", - "gpu": "Nvidia", - "extra_infos": {} - } - ], - "model_config": { - "model_name": "image-model", - "model_id": 111, - "model_version": "v1", - "is_from_open": 0, - "model_storage_url": "https://fedml.s3.us-west-1.amazonaws.com/1666239314792client-package.zip", - "instance_scale_min": 1, - "instance_scale_max": 3, - "inference_engine": "onnx" - }, - "parameters": { - "hidden_size": 128, - "hidden_act": "gelu", - "initializer_range": 0.02, - "vocab_size": 30522, - "hidden_dropout_prob": 0.1, - "num_attention_heads": 2, - "type_vocab_size": 2, - "max_position_embeddings": 512, - "num_hidden_layers": 2, - "intermediate_size": 512, - "attention_probs_dropout_prob": 0.1 - } - } - """ try: MLOpsConfigs.fetch_all_configs() except Exception as e: pass - # get deployment params + # Get deployment params request_json = json.loads(payload) run_id = request_json["end_point_id"] end_point_name = request_json["end_point_name"] @@ -847,6 +787,8 @@ def callback_start_deployment(self, topic, payload): inference_engine = model_config.get("inference_engine", 0) inference_end_point_id = run_id + logging.info("[Master] received start deployment request for end point {}.".format(run_id)) + # Start log processor for current run self.args.run_id = run_id self.args.edge_id = self.edge_id @@ -855,10 +797,9 @@ def callback_start_deployment(self, topic, payload): ServerConstants.FEDML_LOG_SOURCE_TYPE_MODEL_END_POINT) MLOpsRuntimeLogDaemon.get_instance(self.args).start_log_processor(run_id, self.edge_id) - logging.info("callback_start_deployment {}".format(payload)) - # self.ota_upgrade(payload, request_json) + # Add additional parameters to the request_json run_id = inference_end_point_id self.args.run_id = run_id self.run_id = run_id @@ -866,15 +807,14 @@ def callback_start_deployment(self, topic, payload): self.request_json = request_json run_id_str = str(run_id) self.running_request_json[run_id_str] = request_json - self.request_json["master_node_ip"] = self.get_ip_address(self.request_json) - FedMLModelCache.get_instance().set_redis_params(self.redis_addr, self.redis_port, self.redis_password) - # Target status of the devices + FedMLModelCache.get_instance().set_redis_params(self.redis_addr, self.redis_port, self.redis_password) FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ set_end_point_device_info(request_json["end_point_id"], end_point_name, json.dumps(device_objs)) + # Setup Token usr_indicated_token = self.get_usr_indicated_token(request_json) if usr_indicated_token != "": logging.info(f"Change Token from{token} to {usr_indicated_token}") @@ -882,18 +822,16 @@ def callback_start_deployment(self, topic, payload): FedMLModelCache.get_instance(self.redis_addr, self.redis_port). \ set_end_point_token(run_id, end_point_name, model_name, token) - ServerConstants.save_runner_infos(self.args.device_id + "." + self.args.os_name, self.edge_id, run_id=run_id) - self.subscribe_slave_devices_message(request_json) - # Send stage: MODEL_DEPLOYMENT_STAGE1 = "Received" + # Report stage to mlops: MODEL_DEPLOYMENT_STAGE1 = "Received" self.send_deployment_stages(self.run_id, model_name, model_id, "", ServerConstants.MODEL_DEPLOYMENT_STAGE1["index"], ServerConstants.MODEL_DEPLOYMENT_STAGE1["text"], "Received request for end point {}".format(run_id)) - # Send stage: MODEL_DEPLOYMENT_STAGE2 = "Initializing" + # Report stage to mlops: MODEL_DEPLOYMENT_STAGE2 = "Initializing" self.send_deployment_stages(self.run_id, model_name, model_id, "", ServerConstants.MODEL_DEPLOYMENT_STAGE2["index"], @@ -905,7 +843,6 @@ def callback_start_deployment(self, topic, payload): if self.run_as_edge_server_and_agent: # Replica Controller is per deployment replica_controller = FedMLDeviceReplicaController(self.edge_id, self.request_json) - logging.info(f"Start Diff Replica controller for run {run_id} on edge {self.edge_id}") # Prepare num diff new_request_with_num_diff = replica_controller.generate_diff_to_request_json() @@ -917,6 +854,7 @@ def callback_start_deployment(self, topic, payload): self.running_request_json[run_id_str] = new_request_with_version_diff request_json = new_request_with_version_diff + # Init the model runner server_runner = FedMLServerRunner( self.args, run_id=run_id, request_json=request_json, agent_config=self.agent_config ) @@ -928,6 +866,9 @@ def callback_start_deployment(self, topic, payload): server_runner.redis_password = self.redis_password server_runner.replica_controller = replica_controller + logging.info(f"[Master] new request for id {run_id_str}") + logging.info(f"[Master] model runner mapping before: {self.model_runner_mapping.items()}") + self.run_process_event_map[run_id_str] = multiprocessing.Event() self.run_process_event_map[run_id_str].clear() server_runner.run_process_event = self.run_process_event_map[run_id_str] @@ -936,6 +877,8 @@ def callback_start_deployment(self, topic, payload): server_runner.run_process_completed_event = self.run_process_completed_event_map[run_id_str] self.model_runner_mapping[run_id_str] = server_runner + logging.info(f"[Master] model runner mapping after: {self.model_runner_mapping.items()}") + # This subprocess will copy the server_runner and run it, but they are not the same object server_process = Process(target=server_runner.run, args=( self.run_process_event_map[run_id_str], self.run_process_completed_event_map[run_id_str] @@ -1580,23 +1523,17 @@ def subscribe_slave_devices_message(self, request_json): return run_id = request_json["run_id"] edge_id_list = request_json["device_ids"] - logging.info("Edge ids: " + str(edge_id_list)) for edge_id in edge_id_list: if str(edge_id) == str(self.edge_id): continue + # subscribe deployment result message for each model device - deployment_results_topic = "model_device/model_device/return_deployment_result/{}".format(edge_id) + deployment_results_topic = "model_device/model_device/return_deployment_result/{}/{}".format( + run_id, edge_id) + self.mqtt_mgr.add_message_listener(deployment_results_topic, self.callback_deployment_result_message) self.mqtt_mgr.subscribe_msg(deployment_results_topic) - # subscribe deployment status message for each model device - deployment_status_topic = "model_device/model_device/return_deployment_status/{}".format(edge_id) - self.mqtt_mgr.add_message_listener(deployment_status_topic, self.callback_deployment_status_message) - self.mqtt_mgr.subscribe_msg(deployment_status_topic) - - logging.info("subscribe device messages {}, {}".format( - deployment_results_topic, deployment_status_topic)) - def on_agent_mqtt_connected(self, mqtt_client_object): # The MQTT message topic format is as follows: // diff --git a/python/fedml/core/mlops/mlops_runtime_log_daemon.py b/python/fedml/core/mlops/mlops_runtime_log_daemon.py index 401de34e93..9f8d83120b 100644 --- a/python/fedml/core/mlops/mlops_runtime_log_daemon.py +++ b/python/fedml/core/mlops/mlops_runtime_log_daemon.py @@ -1,5 +1,6 @@ import argparse import json +import logging import multiprocess as multiprocessing import os @@ -228,7 +229,7 @@ def should_ignore_log_line(log_line): return False def log_process(self, process_event): - print(f"Log uploading process id {os.getpid()}, run id {self.run_id}, edge id {self.device_id}") + logging.info(f"Log uploading process id {os.getpid()}, run id {self.run_id}, edge id {self.device_id}") self.log_process_event = process_event From 250347d1124f81c631ab4fe9ff7b1d3dbf1e6b22 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 19 Mar 2024 12:32:07 +0800 Subject: [PATCH 086/135] [CoreEngine] Use the original url to download packages. --- python/fedml/computing/scheduler/master/server_runner.py | 3 +-- .../scheduler/model_scheduler/device_client_runner.py | 6 ++---- python/fedml/computing/scheduler/slave/client_runner.py | 3 +-- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/python/fedml/computing/scheduler/master/server_runner.py b/python/fedml/computing/scheduler/master/server_runner.py index e88ab9a2f9..0c83476297 100755 --- a/python/fedml/computing/scheduler/master/server_runner.py +++ b/python/fedml/computing/scheduler/master/server_runner.py @@ -228,8 +228,7 @@ def retrieve_and_unzip_package(self, package_name, package_url): local_package_file = os.path.join(local_package_path, f"fedml_run_{self.run_id}_{filename_without_extension}") if os.path.exists(local_package_file): os.remove(local_package_file) - package_url_without_query_path = urljoin(package_url, urlparse(package_url).path) - urllib.request.urlretrieve(package_url_without_query_path, local_package_file, + urllib.request.urlretrieve(package_url, local_package_file, reporthook=self.package_download_progress) unzip_package_path = os.path.join(ClientConstants.get_package_unzip_dir(), f"unzip_fedml_run_{self.run_id}_{filename_without_extension}") diff --git a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py index b3732b6a8d..faae6f0af6 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_client_runner.py @@ -147,8 +147,7 @@ def retrieve_and_unzip_package(self, package_name, package_url): os.remove(local_package_file) logging.info("Download from package_url {}".format(package_url)) - package_url_without_query_path = urljoin(package_url, urlparse(package_url).path) - urllib.request.urlretrieve(package_url_without_query_path, local_package_file, + urllib.request.urlretrieve(package_url, local_package_file, reporthook=self.package_download_progress) unzip_package_path = os.path.join(ClientConstants.get_package_unzip_dir(), f"unzip_fedml_run_{self.run_id}_{self.edge_id}_{filename_without_extension}") @@ -174,8 +173,7 @@ def retrieve_binary_model_file(self, package_name, package_url): local_package_file = "{}".format(os.path.join(local_package_path, package_name)) if os.path.exists(local_package_file): os.remove(local_package_file) - package_url_without_query_path = urljoin(package_url, urlparse(package_url).path) - urllib.request.urlretrieve(package_url_without_query_path, local_package_file, + urllib.request.urlretrieve(package_url, local_package_file, reporthook=self.package_download_progress) unzip_package_path = os.path.join(unzip_package_path, package_name) diff --git a/python/fedml/computing/scheduler/slave/client_runner.py b/python/fedml/computing/scheduler/slave/client_runner.py index 8ff0500990..52228e84ff 100755 --- a/python/fedml/computing/scheduler/slave/client_runner.py +++ b/python/fedml/computing/scheduler/slave/client_runner.py @@ -259,8 +259,7 @@ def retrieve_and_unzip_package(self, package_name, package_url): local_package_file = os.path.join(local_package_path, f"fedml_run_{self.run_id}_{filename_without_extension}") if os.path.exists(local_package_file): os.remove(local_package_file) - package_url_without_query_path = urljoin(package_url, urlparse(package_url).path) - urllib.request.urlretrieve(package_url_without_query_path, local_package_file, + urllib.request.urlretrieve(package_url, local_package_file, reporthook=self.package_download_progress) unzip_package_path = os.path.join(ClientConstants.get_package_unzip_dir(), f"unzip_fedml_run_{self.run_id}_{filename_without_extension}") From 3a4efbfa2e3d1f23a46ad6fdfbaa5d79b36bf096 Mon Sep 17 00:00:00 2001 From: Raphael Jin Date: Tue, 19 Mar 2024 15:14:15 -0700 Subject: [PATCH 087/135] [Deploy] Fix edge case of result callback (send_next_scroll_update_msg); Reformat Logs. --- .../device_replica_controller.py | 17 +++++++++--- .../model_scheduler/device_server_runner.py | 27 ++++++++++++++----- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py b/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py index 06ef3ed8e9..85c7ec2db6 100644 --- a/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_replica_controller.py @@ -286,6 +286,11 @@ def is_all_replica_num_reconciled(self): """ Check if all the replicas are ready. Including the number and version. """ + logging.info(f"[Replica Controller] [endpoint {self.e_id} ] " + f"intermediate_replica_num: {self.intermediate_replica_num}") + logging.info(f"[Replica Controller] [endpoint {self.e_id} ] " + f"target_replica_num: {self.target_replica_num}") + for id, replica_no in self.intermediate_replica_num.items(): if id not in self.target_replica_num: # Delete all replica in this device if replica_no != 0: @@ -300,10 +305,6 @@ def is_all_replica_num_reconciled(self): return False logging.info(f"[Replica Controller] [endpoint {self.e_id} ] Replicas are reconciled as expected.") - logging.info(f"[Replica Controller] [endpoint {self.e_id} ] " - f"intermediate_replica_num: {self.intermediate_replica_num}") - logging.info(f"[Replica Controller] [endpoint {self.e_id} ] " - f"target_replica_num: {self.target_replica_num}") return True def get_first_chunk_devices_replica_update(self): @@ -414,10 +415,18 @@ def is_all_replica_version_reconciled(self): if self.total_replica_version_diff_num == 0: return True + logging.info(f"[Replica Controller] [endpoint {self.e_id} ] " + f"intermediate_replica_version: {self.intermediate_replica_version}") + logging.info(f"[Replica Controller] [endpoint {self.e_id} ] " + f"target_replica_version: {self.target_replica_version}") + for id, device_replicas_version in self.intermediate_replica_version.items(): for replica_no, version in device_replicas_version.items(): if version != self.target_replica_version: return False + + logging.info(f"[Replica Controller] [endpoint {self.e_id} ] Replicas are reconciled as expected.") + return True def init_first_update_device_replica_mapping(self): diff --git a/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py b/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py index b3051b6279..fb71d3e373 100755 --- a/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py +++ b/python/fedml/computing/scheduler/model_scheduler/device_server_runner.py @@ -287,7 +287,8 @@ def parse_model_run_params(self, running_json): def inference_run(self): # run_id, end_point_name, token, user_id, user_name, device_ids, device_objs, model_config, model_name, \ # model_id, model_storage_url, scale_min, scale_max, inference_engine, model_is_from_open, \ - # inference_end_point_id, use_gpu, memory_size, model_version, inference_port = self.parse_model_run_params(self.request_json) + # inference_end_point_id, use_gpu, memory_size, model_version, inference_port = + # self.parse_model_run_params(self.request_json) # # inference_server = FedMLModelServingServer(self.args, # end_point_name, @@ -530,6 +531,9 @@ def cleanup_run_when_deploy_failed(self): self.callback_delete_deployment(topic, payload=json.dumps(self.request_json)) def callback_deployment_result_message(self, topic=None, payload=None): + """ + This method is called when a deployment result is received from a worker device. + """ # Save deployment result to local cache topic_splits = str(topic).split('/') device_id = topic_splits[-1] @@ -540,9 +544,12 @@ def callback_deployment_result_message(self, topic=None, payload=None): model_name = payload_json["model_name"] model_version = payload_json["model_version"] model_status = payload_json["model_status"] - replica_no = payload_json.get("replica_no", None) # Idx start from 1 + replica_no = payload_json.get("replica_no", None) # "no" Idx start from 1 run_id_str = str(end_point_id) + assert run_id_str in self.model_runner_mapping, (f"Run id {run_id_str} is not in the model runner mapping." + f"Current mapping {self.model_runner_mapping}.") + # Set redis + sqlite deployment result FedMLModelCache.get_instance().set_redis_params(self.redis_addr, self.redis_port, self.redis_password) @@ -574,16 +581,18 @@ def callback_deployment_result_message(self, topic=None, payload=None): self.send_next_scroll_update_msg(device_id, replica_no) # Update the global deployment result mapping - if self.slave_deployment_results_mapping.get(run_id_str, None) is None: + if run_id_str not in self.slave_deployment_results_mapping: self.slave_deployment_results_mapping[run_id_str] = dict() - self.slave_deployment_results_mapping[run_id_str][str(device_id)] = model_status + if str(device_id) not in self.slave_deployment_results_mapping[run_id_str]: + self.slave_deployment_results_mapping[run_id_str][str(device_id)] = dict() + self.slave_deployment_results_mapping[run_id_str][str(device_id)][str(replica_no)] = model_status - logging.info("callback_deployment_result_message: topic {}, payload {}, mapping {}.".format( + logging.info("callback_deployment_result_message: topic {}, payload {}, result mapping {}.".format( topic, payload, self.slave_deployment_results_mapping[run_id_str])) request_json = self.running_request_json.get(run_id_str, None) if request_json is None: - logging.error(f"The endpoint {end_point_id} is not running.") + logging.error(f"The endpoint {end_point_id} is no longer running.") self.send_deployment_status( end_point_id, end_point_name, payload_json["model_name"], "", ServerConstants.MSG_MODELOPS_DEPLOYMENT_STATUS_FAILED) @@ -595,7 +604,7 @@ def callback_deployment_result_message(self, topic=None, payload=None): ''' When all the devices have finished the add / delete / update operation ''' - # 1. We should generate one unified inference api + # Generate one unified inference api # Note that here we use the gateway port instead of the inference port that is used by the slave device model_config_parameters = request_json["parameters"] inference_port = model_config_parameters.get("server_internal_port", @@ -940,6 +949,10 @@ def delete_device_replica_info_on_master(self, edge_id_replica_no_dict): logging.info(f"Deleted the record of the replaced device {delete_device_result_list}") def send_next_scroll_update_msg(self, device_id, replica_no): + """ + Send the next scroll update msg to the devices if needed. + If there is no need for the next scroll update, directly return. + """ if replica_no is None: return From a8c605c9e3a20523cc1ef5e54a4df8e5e8411e6f Mon Sep 17 00:00:00 2001 From: Zijian Hu Date: Fri, 8 Mar 2024 15:10:16 -0800 Subject: [PATCH 088/135] [unitedllm, train.llm] migrate & integrate UnitedLLM --- python/fedml/train/llm/configurations.py | 15 + python/fedml/train/llm/constants.py | 12 +- python/fedml/train/llm/distributed.py | 14 +- python/fedml/train/llm/modeling_utils.py | 23 +- python/spotlight_prj/fedllm/README.md | 2 +- .../fedllm/fedml_config/fedml_config.yaml | 2 +- .../fedllm/mlops_config/fedml_config.yaml | 2 +- python/spotlight_prj/unitedllm/.gitattributes | 25 + python/spotlight_prj/unitedllm/.gitignore | 41 + python/spotlight_prj/unitedllm/LICENSE | 201 +++++ python/spotlight_prj/unitedllm/README.md | 358 ++++++++- python/spotlight_prj/unitedllm/__init__.py | 0 .../assets/Llama/huggingface_llama_repo.png | Bin 0 -> 197602 bytes .../unitedllm/assets/MLOps/FedML_Home.png | Bin 0 -> 313223 bytes .../assets/MLOps/FedML_Home_AccountID.png | Bin 0 -> 344207 bytes .../MLOps_Experimental_Tracking_System.png | Bin 0 -> 284506 bytes ...ps_Experimental_Tracking_Visualization.png | Bin 0 -> 215649 bytes .../MLOps/Octopus_Application_Step_1.png | Bin 0 -> 62664 bytes .../MLOps/Octopus_Create_Application_1.png | Bin 0 -> 96147 bytes .../MLOps/Octopus_Create_Application_2.png | Bin 0 -> 106712 bytes .../assets/MLOps/Octopus_Edge_Devices.png | Bin 0 -> 115980 bytes .../assets/MLOps/Octopus_New_Project_1.png | Bin 0 -> 74929 bytes .../assets/MLOps/Octopus_New_Project_2.png | Bin 0 -> 26468 bytes .../assets/MLOps/Octopus_Project_Run_1.png | Bin 0 -> 86551 bytes .../assets/MLOps/Octopus_Project_Run_2.png | Bin 0 -> 110109 bytes .../assets/MLOps/Octopus_Project_Run_3.png | Bin 0 -> 127395 bytes .../assets/MLOps/Octopus_Project_Run_4.png | Bin 0 -> 137861 bytes .../assets/fedml_logo_light_mode.png | Bin 0 -> 10328 bytes .../configs/deepspeed/ds_z3_bf16_config.json | 32 + .../configs/deepspeed/ds_z3_cpu_config.json | 40 + .../unitedllm/fedml_config/bootstrap.sh | 12 + .../unitedllm/fedml_config/fedml_config.yaml | 90 +++ .../unitedllm/launch_unitedllm.py | 203 +++++ .../unitedllm/mlops_config/bootstrap.sh | 15 + .../unitedllm/mlops_config/fedml_config.yaml | 90 +++ .../spotlight_prj/unitedllm/requirements.txt | 20 + .../unitedllm/requirements_unitedllm.txt | 2 + python/spotlight_prj/unitedllm/run_train.py | 89 +++ .../spotlight_prj/unitedllm/run_unitedllm.py | 732 ++++++++++++++++++ .../unitedllm/scripts/build/fedml_build.sh | 64 ++ .../unitedllm/scripts/run_fedml_client.sh | 35 + .../unitedllm/scripts/run_fedml_server.sh | 35 + .../spotlight_prj/unitedllm/scripts/setup.sh | 68 ++ .../spotlight_prj/unitedllm/scripts/train.sh | 45 ++ .../unitedllm/scripts/train_auto.sh | 61 ++ .../unitedllm/scripts/train_ddp.sh | 57 ++ .../unitedllm/scripts/train_deepspeed.sh | 64 ++ .../spotlight_prj/unitedllm/src/__init__.py | 0 .../unitedllm/src/configurations.py | 158 ++++ .../unitedllm/src/modeling_utils.py | 100 +++ .../spotlight_prj/unitedllm/src/peft_utils.py | 75 ++ .../unitedllm/src/trainer_callback.py | 102 +++ python/spotlight_prj/unitedllm/src/typing.py | 2 + .../unitedllm/src/unitedllm_trainer.py | 162 ++++ python/spotlight_prj/unitedllm/src/utils.py | 65 ++ 55 files changed, 3098 insertions(+), 15 deletions(-) create mode 100644 python/spotlight_prj/unitedllm/.gitattributes create mode 100644 python/spotlight_prj/unitedllm/.gitignore create mode 100644 python/spotlight_prj/unitedllm/LICENSE create mode 100644 python/spotlight_prj/unitedllm/__init__.py create mode 100644 python/spotlight_prj/unitedllm/assets/Llama/huggingface_llama_repo.png create mode 100644 python/spotlight_prj/unitedllm/assets/MLOps/FedML_Home.png create mode 100644 python/spotlight_prj/unitedllm/assets/MLOps/FedML_Home_AccountID.png create mode 100644 python/spotlight_prj/unitedllm/assets/MLOps/MLOps_Experimental_Tracking_System.png create mode 100644 python/spotlight_prj/unitedllm/assets/MLOps/MLOps_Experimental_Tracking_Visualization.png create mode 100644 python/spotlight_prj/unitedllm/assets/MLOps/Octopus_Application_Step_1.png create mode 100644 python/spotlight_prj/unitedllm/assets/MLOps/Octopus_Create_Application_1.png create mode 100644 python/spotlight_prj/unitedllm/assets/MLOps/Octopus_Create_Application_2.png create mode 100644 python/spotlight_prj/unitedllm/assets/MLOps/Octopus_Edge_Devices.png create mode 100644 python/spotlight_prj/unitedllm/assets/MLOps/Octopus_New_Project_1.png create mode 100644 python/spotlight_prj/unitedllm/assets/MLOps/Octopus_New_Project_2.png create mode 100644 python/spotlight_prj/unitedllm/assets/MLOps/Octopus_Project_Run_1.png create mode 100644 python/spotlight_prj/unitedllm/assets/MLOps/Octopus_Project_Run_2.png create mode 100644 python/spotlight_prj/unitedllm/assets/MLOps/Octopus_Project_Run_3.png create mode 100644 python/spotlight_prj/unitedllm/assets/MLOps/Octopus_Project_Run_4.png create mode 100644 python/spotlight_prj/unitedllm/assets/fedml_logo_light_mode.png create mode 100644 python/spotlight_prj/unitedllm/configs/deepspeed/ds_z3_bf16_config.json create mode 100644 python/spotlight_prj/unitedllm/configs/deepspeed/ds_z3_cpu_config.json create mode 100644 python/spotlight_prj/unitedllm/fedml_config/bootstrap.sh create mode 100644 python/spotlight_prj/unitedllm/fedml_config/fedml_config.yaml create mode 100644 python/spotlight_prj/unitedllm/launch_unitedllm.py create mode 100644 python/spotlight_prj/unitedllm/mlops_config/bootstrap.sh create mode 100644 python/spotlight_prj/unitedllm/mlops_config/fedml_config.yaml create mode 100644 python/spotlight_prj/unitedllm/requirements.txt create mode 100644 python/spotlight_prj/unitedllm/requirements_unitedllm.txt create mode 100644 python/spotlight_prj/unitedllm/run_train.py create mode 100644 python/spotlight_prj/unitedllm/run_unitedllm.py create mode 100644 python/spotlight_prj/unitedllm/scripts/build/fedml_build.sh create mode 100644 python/spotlight_prj/unitedllm/scripts/run_fedml_client.sh create mode 100644 python/spotlight_prj/unitedllm/scripts/run_fedml_server.sh create mode 100644 python/spotlight_prj/unitedllm/scripts/setup.sh create mode 100644 python/spotlight_prj/unitedllm/scripts/train.sh create mode 100644 python/spotlight_prj/unitedllm/scripts/train_auto.sh create mode 100644 python/spotlight_prj/unitedllm/scripts/train_ddp.sh create mode 100644 python/spotlight_prj/unitedllm/scripts/train_deepspeed.sh create mode 100644 python/spotlight_prj/unitedllm/src/__init__.py create mode 100644 python/spotlight_prj/unitedllm/src/configurations.py create mode 100644 python/spotlight_prj/unitedllm/src/modeling_utils.py create mode 100644 python/spotlight_prj/unitedllm/src/peft_utils.py create mode 100644 python/spotlight_prj/unitedllm/src/trainer_callback.py create mode 100644 python/spotlight_prj/unitedllm/src/typing.py create mode 100644 python/spotlight_prj/unitedllm/src/unitedllm_trainer.py create mode 100644 python/spotlight_prj/unitedllm/src/utils.py diff --git a/python/fedml/train/llm/configurations.py b/python/fedml/train/llm/configurations.py index 68f8b82510..dfff5427da 100644 --- a/python/fedml/train/llm/configurations.py +++ b/python/fedml/train/llm/configurations.py @@ -76,6 +76,21 @@ def __post_init__(self): super().__post_init__() + if ( + compare_versions("torch", ">", "1.12") and + compare_versions("torch", "<=", "2.0.1") and + self.world_size > torch.cuda.device_count() and + self.full_determinism + ): + # when using multi-node with full_determinism + warnings.warn( + f"Multi-node training with 1.12 < torch <= 2.0.1 could lead to process hanging." + f" Setting `full_determinism` to `False`." + f" See https://github.com/huggingface/transformers/issues/22363#issuecomment-1483163515" + f" for detail." + ) + self.full_determinism = False + # for `transformers>=4.35.0`, `gradient_checkpointing_kwargs` is added to allow passing arguments directly to # `torch.utils.checkpoint.checkpoint` if hasattr(self, "gradient_checkpointing_kwargs"): diff --git a/python/fedml/train/llm/constants.py b/python/fedml/train/llm/constants.py index fb5fcb76f4..743522c769 100644 --- a/python/fedml/train/llm/constants.py +++ b/python/fedml/train/llm/constants.py @@ -16,6 +16,14 @@ "EleutherAI/pythia-2.8b", "EleutherAI/pythia-6.9b", "EleutherAI/pythia-12b", + "EleutherAI/pythia-70m-deduped", + "EleutherAI/pythia-160m-deduped", + "EleutherAI/pythia-410m-deduped", + "EleutherAI/pythia-1b-deduped", + "EleutherAI/pythia-1.4b-deduped", + "EleutherAI/pythia-2.8b-deduped", + "EleutherAI/pythia-6.9b-deduped", + "EleutherAI/pythia-12b-deduped", "databricks/dolly-v2-3b", "databricks/dolly-v2-7b", "databricks/dolly-v2-12b", @@ -28,8 +36,8 @@ ] DATASET_NAMES = [ - "FedML/PubMedQA_instruction", - "FedML/databricks-dolly-15k-niid", + "fedml/PubMedQA_instruction", + "fedml/databricks-dolly-15k-niid", "databricks/databricks-dolly-15k", "medalpaca/medical_meadow_mediqa", "bitext/Bitext-customer-support-llm-chatbot-training-dataset", diff --git a/python/fedml/train/llm/distributed.py b/python/fedml/train/llm/distributed.py index 6f8abbe636..e7215dab28 100644 --- a/python/fedml/train/llm/distributed.py +++ b/python/fedml/train/llm/distributed.py @@ -1,8 +1,9 @@ from typing import ContextManager, Iterable, Optional, Union -from contextlib import contextmanager, nullcontext +import contextlib +from contextlib import nullcontext -from torch import distributed as dist +from torch import distributed as dist, Tensor from torch.nn import Module, Parameter from .integrations import is_deepspeed_available, is_deepspeed_zero3_enabled @@ -48,14 +49,19 @@ def is_deepspeed_module(module: Union[Module, Parameter, Iterable[Parameter]]) - return False -@contextmanager +# TODO: replace with `@contextmanager` once https://youtrack.jetbrains.com/issue/PY-36444 is fixed +@contextlib.contextmanager def gather_parameter( params: Union[Iterable[Parameter], Parameter], modifier_rank: Optional[int] = None, fwd_module: Optional[Module] = None, enabled: bool = True ) -> ContextManager[None]: - if enabled and is_deepspeed_initialized() and is_deepspeed_zero3_enabled() and is_deepspeed_module(params): + if isinstance(params, Iterable) and not isinstance(params, Tensor): + # handle generator such as `model.parameters()` + params = list(params) + + if enabled and is_deepspeed_initialized() and is_deepspeed_zero3_enabled(): context = GatheredParameters(params, modifier_rank, fwd_module, enabled) else: context = nullcontext() diff --git a/python/fedml/train/llm/modeling_utils.py b/python/fedml/train/llm/modeling_utils.py index 3e9ccec54a..ee3042d00e 100644 --- a/python/fedml/train/llm/modeling_utils.py +++ b/python/fedml/train/llm/modeling_utils.py @@ -147,10 +147,23 @@ def get_max_seq_length(model_or_config: Union[str, ModelConfigType, ModelType], else: raise TypeError(f"\"{type(model_or_config)}\" is not a supported model_or_config type.") - for length_setting in ["n_positions", "max_position_embeddings", "seq_length"]: - embedding_size = getattr(config, length_setting, None) - if embedding_size is not None: - return embedding_size + for length_setting in [ + # Llama, GPTNeoX, OPT + "max_position_embeddings", + # GPT-2 + "n_positions", + # MPT + "max_seq_len", + # ChatGLM2 + "seq_length", + # Others + "max_sequence_length", + "max_seq_length", + "seq_len", + ]: + model_context_length = getattr(config, length_setting, None) + if model_context_length is not None: + return model_context_length else: return None @@ -270,7 +283,7 @@ def to_device(data: T, device: Union[torch.device, str], non_blocking: bool = Fa def to_dtype( data: T, - dtype: torch.dtype, + dtype: Union[torch.dtype, str], non_blocking: bool = False, floating_point_only: bool = True ) -> T: diff --git a/python/spotlight_prj/fedllm/README.md b/python/spotlight_prj/fedllm/README.md index 9114956b1a..72974f8a3c 100644 --- a/python/spotlight_prj/fedllm/README.md +++ b/python/spotlight_prj/fedllm/README.md @@ -148,7 +148,7 @@ data_args: model_args: skip_log_model_net: True # toggle auto model input shape inference; if set to `False`, could slow down the training - model_name_or_path: "EleutherAI/pythia-70m" # choose from `MODEL_NAMES` in `src/constants.py` + model_name_or_path: "EleutherAI/pythia-70m" # choose any decoder-only hugging face model peft_type: "lora" # need to install `flash_attn` package first, see https://github.com/Dao-AILab/flash-attention for detail use_flash_attention: False diff --git a/python/spotlight_prj/fedllm/fedml_config/fedml_config.yaml b/python/spotlight_prj/fedllm/fedml_config/fedml_config.yaml index a2fbb384ec..562e7dbbb9 100644 --- a/python/spotlight_prj/fedllm/fedml_config/fedml_config.yaml +++ b/python/spotlight_prj/fedllm/fedml_config/fedml_config.yaml @@ -18,7 +18,7 @@ data_args: model_args: skip_log_model_net: True # toggle auto model input shape inference; if set to `False`, could slow down the training - model_name_or_path: "EleutherAI/pythia-70m" # choose from `MODEL_NAMES` in `src/constants.py` + model_name_or_path: "EleutherAI/pythia-70m" # choose any decoder-only hugging face model peft_type: "lora" # need to install `flash_attn` package first, see https://github.com/Dao-AILab/flash-attention for detail use_flash_attention: False diff --git a/python/spotlight_prj/fedllm/mlops_config/fedml_config.yaml b/python/spotlight_prj/fedllm/mlops_config/fedml_config.yaml index 2fc86e901b..bb0b0f03df 100644 --- a/python/spotlight_prj/fedllm/mlops_config/fedml_config.yaml +++ b/python/spotlight_prj/fedllm/mlops_config/fedml_config.yaml @@ -18,7 +18,7 @@ data_args: model_args: skip_log_model_net: True # toggle auto model input shape inference; if set to `False`, could slow down the training - model_name_or_path: "EleutherAI/pythia-70m" # choose from `MODEL_NAMES` in `src/constants.py` + model_name_or_path: "EleutherAI/pythia-70m" # choose any decoder-only hugging face model peft_type: "lora" # need to install `flash_attn` package first, see https://github.com/Dao-AILab/flash-attention for detail use_flash_attention: False diff --git a/python/spotlight_prj/unitedllm/.gitattributes b/python/spotlight_prj/unitedllm/.gitattributes new file mode 100644 index 0000000000..93fa761eb5 --- /dev/null +++ b/python/spotlight_prj/unitedllm/.gitattributes @@ -0,0 +1,25 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.c text +*.h text +*.py text + +# Declare files that will always have CRLF line endings on checkout. +*.sln text eol=crlf + +# Declare files that will always have LF line endings on checkout. +*.sh text eol=lf + +# Denote all files that are truly binary and should not be modified. +*.png binary +*.jpg binary + +# Git LFS tracked files +*.csv filter=lfs diff=lfs merge=lfs -text +*.pdf filter=lfs diff=lfs merge=lfs -text +*.npy filter=lfs diff=lfs merge=lfs -text +*.npz filter=lfs diff=lfs merge=lfs -text +*.hdf5 filter=lfs diff=lfs merge=lfs -text diff --git a/python/spotlight_prj/unitedllm/.gitignore b/python/spotlight_prj/unitedllm/.gitignore new file mode 100644 index 0000000000..0343d3b911 --- /dev/null +++ b/python/spotlight_prj/unitedllm/.gitignore @@ -0,0 +1,41 @@ +# include all in this folder and its subfolders +!/** + +# CMake +cmake-build-*/ + +# JetBrains IDE +.idea/ + +# VS Code +.vscode/ + +# Mac +*.DS_Store + +# Node.js +node_modules/ +package-lock.json + +# Python +__pycache__/ +*.pyc +*.egg-info +/build +/dist + +# Jupyter notebook +.ipynb_checkpoints + +# pyenv files +.python-version + +# wandb +/wandb + +# project files +*_host_file +/.data +/.logs +/cache +devops/geo-distributed-cluster/* diff --git a/python/spotlight_prj/unitedllm/LICENSE b/python/spotlight_prj/unitedllm/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/python/spotlight_prj/unitedllm/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/python/spotlight_prj/unitedllm/README.md b/python/spotlight_prj/unitedllm/README.md index 5a675e5284..601a3895c4 100644 --- a/python/spotlight_prj/unitedllm/README.md +++ b/python/spotlight_prj/unitedllm/README.md @@ -1 +1,357 @@ -# UnitedLLM \ No newline at end of file +
+ +
+ +# UnitedLLM: Communication Efficient Decentralized Training of Large Models + +[UnitedLLM](https://blog.fedml.ai/releasing-fedllm-build-your-own-large-language-models-on-proprietary-data-using-the-fedml-platform/) +is an MLOps-supported training pipeline for communication efficient geo-distributed pretraining of large models. + +## How to Use Llama 2 + +Our UnitedLLM example uses Pythia by default, but we recently added support for Llama2. +If you'd like to use Llama2, please see the following instructions before getting started. + +To use [Llama 2](https://ai.meta.com/llama/), you need to apply access from Meta and request Meta's private +Hugging Face repo access. + +1. Make sure your `transformers` version is `4.31.0` or newer. You could update your transformers via + `pip install --upgrade transformers`. +2. Please visit the [Meta website](https://ai.meta.com/resources/models-and-libraries/llama-downloads/) and apply for + access. +2. Apply for [Meta's private repo](https://huggingface.co/meta-llama/Llama-2-7b-hf) + on [Hugging Face](https://huggingface.co/meta-llama/Llama-2-7b-hf). See below image for detail. + ![Meta's private repo on Hugging Face](assets/Llama/huggingface_llama_repo.png) +3. Once both access are granted, you can start using Llama with UnitedLLM + 1. For centralized/conventional training, pass `--model_name_or_path "meta-llama/Llama-2-7b-hf"` to the training script. + 2. For federated training, update the fedml_config as follow + ```yaml + model_args: + model_name_or_path: "meta-llama/Llama-2-7b-hf" + ... + ``` + +> **Warning** +> Since Llama 2 is on a private Hugging Face repo, you need to either login to Hugging Face or provide your access token. +> - To login to huggingface (see https://huggingface.co/settings/tokens for detail), run `huggingface-cli login` in + command line. +> - To pass an access token, you need to do one of the following: +> - Set environment variable `HUGGING_FACE_HUB_TOKEN=""` +> - For centralized/conventional training, pass `--auth_token ""` in the command line. +> - For federated training, update the [fedml_config.yaml](fedml_config/fedml_config.yaml) as follow: +> - ```yaml +> model_args: +> auth_token: "" +> ... +> ``` + +## Getting Started + +Clone the repo then go to UnitedLLM directory: + +```shell +# clone the repo and the submodules +git clone https://github.com/FedML-AI/FedML.git + +# go to the project directory +cd python/spotlight_prj/unitedllm +``` + +Install dependencies with the following command: + +```shell +pip install -r requirements.txt +``` + +See [Dependencies](#dependencies) for more information on the dependency versions. + +### Update the Repo + +Update the repo and the submodules: + +```shell +git pull --recurse-submodules +``` + +### Prepare Dataset + +Run the following command to download the example datasets. + +```shell +bash scripts/setup.sh +``` + +### Conventional/Centralized Training + +See [LLM Train examples](https://github.com/FedML-AI/FedML/tree/master/python/examples/train/llm_train) for detail. + +### Decentralized Cross-cloud Training with FedML + +#### 1. Install FedML + +Install FedML with the following command + +```shell +pip install fedml +``` + +#### 2. Prepare a Configuration File + +To train/fine-tune in federated setting, you need to provide a FedML config file. +A concrete example can be found in [fedml_config/fedml_config.yaml](fedml_config/fedml_config.yaml). + +```yaml +common_args: + training_type: "cross_cloud" # decentralized training type, we recommend `cross_cloud` for LLMs + scenario: "horizontal" # decentralized training scenario, we recommend `horizontal` for LLMs + use_customized_hierarchical: True # if `True`, will use customized hierarchical cross-cloud; this could improve the training stability + random_seed: 0 + +environment_args: + bootstrap: fedml_config/bootstrap.sh # change to "config/bootstrap.sh" when using MLOps + launcher: "auto" # program launcher, choose from `auto`, `torch`, `deepspeed` + +data_args: + dataset: "databricks-dolly" # dataset name; this setting is required for FedML built-in datasets + dataset_name: "fedml/databricks-dolly-15k-niid" + dataset_path: [ ] + client_dataset_path: [ ] + test_dataset_size: 200 # this is ignored when `dataset_path` has more than 1 element + remove_long_seq: True # if `True` remove all data whose sequence length > max_seq_length + truncate_long_seq: True # if `True` truncate long sequences whose length > max_seq_length + +model_args: + skip_log_model_net: True # toggle auto model input shape inference; if set to `False`, could slow down the training + model_name_or_path: "EleutherAI/pythia-70m" # choose any decoder-only hugging face model + # need to install `flash_attn` package first, see https://github.com/Dao-AILab/flash-attention for detail + use_flash_attention: False + load_pretrained: False # Whether to load pretrained weights + # PEFT configs + peft_type: "loft" + +train_args: + federated_optimizer: "FedAvg" + client_optimizer: "adamw_torch" + server_optimizer: "FedAvg" + client_num_in_total: 2 # number of clients + client_num_per_round: 2 # choose from 1~client_num_in_total + comm_round: 5 # number of rounds of aggregation + # below are the same as HuggingFace settings + deepspeed: "configs/deepspeed/ds_z3_bf16_config.json" + ddp_find_unused_parameters: False + seed: 1234 + fp16: False + bf16: False + gradient_checkpointing: True + per_device_train_batch_size: 8 + per_device_eval_batch_size: 8 + gradient_accumulation_steps: 1 + eval_accumulation_steps: 4 + learning_rate: 3.0e-4 + warmup_steps: 50 + output_dir: ".logs/UnitedLLM/{run_id}" + logging_steps: 20 + eval_steps: 200 + save_steps: 200 + save_total_limit: 10 + logging_strategy: "no" + evaluation_strategy: "no" # should be turned off + save_strategy: "no" + save_on_each_node: True + # extra options + # model weights type. + model_dtype: "fp32" # choose from "bf16" | "fp16" | "fp32" + # number of training epoch for each communication round, total epoch is local_num_train_epochs * comm_round + local_num_train_epochs: 1 + # number of training steps for each communication round, total step is local_max_steps * comm_round; + # this option overwrites `local_num_train_epochs`; set to a non-positive value to disable it. + local_max_steps: 200 + +validation_args: + frequency_of_the_test: 1 + test_on_clients: "after_aggregation" # choose from "before_aggregation" | "after_aggregation" | "no" | "both" + is_aggregator_test: False # set to `True` to enable testing on aggregator after each aggregation + test_on_client_ranks: [ 1 ] # the rank of the clients to run test + # Number of updates steps before two checkpoint saves. Set to 0 to disable saving. Set to a negative number or + # null to save after every test (i.e. same as `frequency_of_the_test`). + save_frequency: null + +device_args: + using_gpu: True + +comm_args: + backend: "MQTT_S3" + is_mobile: 0 + +tracking_args: + enable_wandb: False + wandb_only_server: True + +``` + +#### 3. Run FedML + +To launch an experiment, a `RUN_ID` should be provided. For each experiment, the same `RUN_ID` should +be used across all the client(s) and aggregator server. +For clients, `client_rank` is also required. Each client should have a unique `client_rank` and +the value should be in range from 1 to N where N is the number of clients. +`client_rank` is the distributed rank which is similar to an index in an array; each client can be +"indexed" by its rank. + + +> **Note** +> since we use `RUN_ID` to uniquely identify experiments, we recommend that you carefully choose the `RUN_ID`. +> You may also generate a UUID for your `RUN_ID` with built-in Python module `uuid`; +> e.g. use `RUN_ID="$(python3 -c "import uuid; print(uuid.uuid4().hex)")"` in your shell script. + +Example scripts: + +```shell +# run aggregator server +bash scripts/run_fedml_server.sh "$RUN_ID" + +# run client(s) +bash scripts/run_fedml_client.sh 1 "$RUN_ID" +bash scripts/run_fedml_client.sh 2 "$RUN_ID" +bash scripts/run_fedml_client.sh 3 "$RUN_ID" +... +``` + +_See FedML's [Getting Started](https://doc.fedml.ai/starter/getting_started.html) for detail._ + +### Use FedML Octopus (MLOps) for Model Training + +FedML Octopus is a MLOps platform that simplifies model training and deployment. + +We strongly recommend going through our [step-by-step introduction to Octopus](https://blog.fedml.ai/fedml-octopus-getting-started-federated-machine-learning/). + +#### 1. Login or Signup for FedML Account + +_Skip this step if you already have a FedML account._ + +1. Go to [FedML official website](https://open.fedml.ai/login). +2. Go to **Sign Up** and sign up for an account (skip this step if you already have an account). +3. Click **login** to login to your account. + +#### 2. Build package + +Use the following command to build client and aggregator server package for MLOps. + +```shell +fedml build -t $TARGET_TYPE -sf $SOURCE -ep $ENTRY -cf $CONFIG -df $DEST +``` + +> Usage: fedml build [OPTIONS] +> +> Commands for open.fedml.ai MLOps platform +> +> Options: +> +> - `-t`, --type TEXT client or aggregator server? (value: client; server) +> +> - `-sf`, --source_folder TEXT the source code folder path +> +> - `-ep`, --entry_point TEXT the entry point (a .py file) of the source code +> +> - `-cf`, --config_folder TEXT the config folder path +> +> - `-df`, --dest_folder TEXT the destination package folder path +> +> - `--help`, Show this message and exit. + + +To compile an example package, use the following command in the **UnitedLLM root directory**: + +```shell +# build aggregator server package +fedml build -t server -sf . -ep launch_fedllm.py -df build -cf "mlops_config" -ig "build" + +# build client package +fedml build -t client -sf . -ep launch_fedllm.py -df build -cf "mlops_config" -ig "build" +``` + +We also provide an example script for building the packages: +```shell +bash scripts/build/fedml_build.sh +``` + +#### 2. Create an Octopus Application + +1. Once logged in, go to [FedML Octopus](https://open.fedml.ai/octopus/userGuides/index). + ![FedML Home](assets/MLOps/FedML_Home.png) + +2. Go to [My Applications](https://open.fedml.ai/octopus/applications/index), then click `+ New Application` to + create a new application. + ![Octopus Application Page](assets/MLOps/Octopus_Application_Step_1.png) + +3. Enter `Application name` and upload `Server` and `Client` packages. + ![Octopus Create Application 1](assets/MLOps/Octopus_Create_Application_1.png) + If you followed the tutorial, the packages should be located at `build/dist-packages`. + ![Octopus Create Application 2](assets/MLOps/Octopus_Create_Application_2.png) + +#### 3. Create an Octopus Project + +1. Navigate to [Project](https://open.fedml.ai/octopus/project/index) page and click `+ Create new project`. + ![Octopus New Project 1](assets/MLOps/Octopus_New_Project_1.png) + +2. Enter `Group` and select a project group from `Group Name` dropdown menu; there should a default group available. + ![Octopus New Project 2](assets/MLOps/Octopus_New_Project_2.png) + +#### 4. Login from Your Device(s) + +1. Find your account ID from the top-right corner of the page. + ![FedML Home AccountID](assets/MLOps/FedML_Home_AccountID.png) + +2. On your device, login as a client with command `fedml login $account_id`. + +3. On your device (preferably a different physical device), login as a aggregator server with + command `fedml login -s $account_id`. + +4. You should be able to find your devices in [Edge Devices](https://open.fedml.ai/octopus/edgeDevice/edgeApp) page + ![Edge Devices](assets/MLOps/Octopus_Edge_Devices.png) + +5. In the [Project](https://open.fedml.ai/octopus/project/index) page, select the project you just created. + ![Octopus Project Run 1](assets/MLOps/Octopus_Project_Run_1.png) + +#### 5. Start Training + +1. Select `+ Create new run` to create a new experiment. + ![Octopus Project Run 2](assets/MLOps/Octopus_Project_Run_2.png) + +2. Select your **client** and **aggregator server** devices and select **application** from the `Application` dropdown + menu. + ![Octopus_Project_Run_3.png](assets/MLOps/Octopus_Project_Run_3.png) + +3. Select and existing Hyper-parameter Configuration. You can also `Add` and `Delete` configurations. + +4. Click `Start` to start your experiment. + ![Octopus_Project_Run_4.png](assets/MLOps/Octopus_Project_Run_4.png) + +### Experiment Tracking and More with FedML Octopus + +You can easily monitor system performance,and visualize training/evaluation metrics with FedML Octopus. + +![MLOps Experimental Tracking Visualization](assets/MLOps/MLOps_Experimental_Tracking_Visualization.png) +![MLOps Experimental Tracking System](assets/MLOps/MLOps_Experimental_Tracking_System.png) + +**Congratulations! You've completed the UnitedLLM tutorial on FedML!!!** + +Check out [FedML Octopus](https://open.fedml.ai/octopus/index) and our [Video Tutorial](https://youtu.be/Xgm0XEaMlVQ) +for detail. + +### Dependencies + +We have tested our implement with the following setup: + +- Ubuntu `20.04.5 LTS` and `22.04.2 LTS` +- CUDA `11.8`, `11.7` and `11.6` +- Python `3.8.13` and `3.9.16` + - `fedml>=0.8.4a7` + - `torch>=2.0.0,<=2.0.1` + - `torchvision>=0.15.1,<=0.15.2` + - `transformers>=4.31.0,<=4.34.0` + - `peft>=0.4.0,<=0.5.0` + - `datasets>=2.11.0,<=2.14.5` + - `deepspeed>=0.9.1,<=0.10.2` + - `numpy>=1.24.3,<=1.24.4` + - `tensorboard>=2.12.2,<=2.13.0` diff --git a/python/spotlight_prj/unitedllm/__init__.py b/python/spotlight_prj/unitedllm/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/python/spotlight_prj/unitedllm/assets/Llama/huggingface_llama_repo.png b/python/spotlight_prj/unitedllm/assets/Llama/huggingface_llama_repo.png new file mode 100644 index 0000000000000000000000000000000000000000..3e8571a6b6df7c24e8db71563a0ee43d92d8b62c GIT binary patch literal 197602 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�-dT{Eenhfc!%{Axq!;sbx25KX&R~4- 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 literal 0 HcmV?d00001 diff --git a/python/spotlight_prj/unitedllm/assets/MLOps/FedML_Home.png b/python/spotlight_prj/unitedllm/assets/MLOps/FedML_Home.png new file mode 100644 index 0000000000000000000000000000000000000000..f039c749074ab8db5af16cc0e43a4c307dff8ac2 GIT binary patch literal 313223 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 z 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%0D0gTrVp&(JFW2_8Lh4ntLJ~JDQ@x?3lU5KUG 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

    =}ZLM?0)5 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

    >63M> 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