Метод Pyro4 очень медленный при вызове по сети
Я разрабатываю распределенный классификатор kNN с использованием Pyro4 с настройкой клиент-сервер в моей локальной сети Wi-Fi. Сервер владеет набором данных, и они передаются двум клиентам, которые владеют классифицирующей программой. В моем распоряжении две машины, и сервер работает на машине A, а клиенты работают как на машине A, так и на машине B.
После запуска сервера он ожидает подключения двух клиентов. После того, как два клиента зарегистрировались на сервере, сервер разделяет набор данных на два раздела (по одному для каждого клиента), а затем приказывает двум клиентам начать классификацию, используя свою собственную долю набора данных. Сервер делает это путем удаленного вызова клиентского метода classify() по сети.
Когда классификация выполняется на одном компьютере, для классификации на наборе данных размером 500 требуется всего 0,362884 с. Из-за моей распределенной настройки я ожидал, что время классификации будет сокращено вдвое, потому что одновременно работают два компьютера., Однако, к моему удивлению, потребовалось 2,284536 с, чтобы классифицировать набор данных того же размера на компьютере, на котором работает сервер, и еще дольше (3,029238 с) на моем другом компьютере в локальной сети.
Где может быть узкое место? Если мое понимание верно, не должно быть удаленного взаимодействия, за исключением случаев, когда (1) сервер удаленно вызывает метод classify() со своими долями (до классификации), и (2) когда клиент возвращает прогнозы на сервер, один раз классификация сделана (после классификации). Конечно, не должно быть удаленной связи между машинами в сети во время классификации, чтобы вызвать какие-либо узкие места?
Код сервера (показывающий удаленный вызов классификации)
# Tell clients to initiate classification
def initiateClassification(self):
with Pyro4.locateNS() as ns:
print('Expected number of clients met; will now initiate classification for all clients.')
# Compile all client classification threads
clientThreads = []
# Invoke each client's classifiers
for classifier, classifierUri in ns.list(prefix=self._classifierName).items():
print('Initiating classifier of client ' + classifier + ' with URI ' + classifierUri + '...', end='')
# Get the specific client's classifier object
clientClassifier = Pyro4.Proxy(classifierUri)
# Derive the id from its classifier name
id = classifier.replace('client.classifier-', '')
# Prepare the split of the dataset for the client
trainSet, testSet = self.getShares(id)
# REMOTE INVOCATION SECTION #
# clientClassifier.classify is the remote kNN classification method in the client
# We remotely invoke it, providing their dataset splits
# It doesn't contain any remote invocations itself, aside from when it submits the predictions to the server when it's finished classifying
# We run it in a new thread to avoid blocking the server
clientThread = Thread(
name='thread-' + clientClassifier.clientName,
target=clientClassifier.classify,
args=(trainSet, testSet)
)
# END REMOTE INVOCATION SECTION #
clientThread.start()
# Take note of this thread
clientThreads.append(clientThread)
print('initiated.')
# Wait until all client threads have finished (which means they're done classifying)
for clientThread in clientThreads:
clientThread.join()
# Stop each client
for classifier, classifierUri in ns.list(prefix=self._classifierName).items():
print('Stopping client with classifier URI ' + classifierUri + '...', end='')
# Get the client's classifier object
clientClassifier = Pyro4.Proxy(classifierUri)
# Stop that client
clientClassifier.stop()
print('stopped.')
Приложение Вместо запуска нового потока для каждого запускаемого клиентского классификатора, я мог бы просто пометить клиентский метод classify() как односторонний (используя @ Pyro4.oneway). Я попробовал это, и это не имело никакого значения с точки зрения скорости.
TL; DR: я избегал надлежащей классификации в сети, потому что думал обо всех издержках связи. Я спроектировал общение так, чтобы оно было двояким: до и после классификации, просто так. Но по какой-то причине классификация была еще более медленной из-за огромного фактора при вызове по сети, в отличие от того, когда я просто запускаю ее локально на своей машине.