-# Copyright (c) 2020 Cisco and/or its affiliates.
+# Copyright (c) 2022 Cisco and/or its affiliates.
# 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:
zeros += 1
# TODO: Ratio of fill rate to drain rate seems to have
# exponential impact. Make it configurable, or is 4:3 good enough?
- if measurement.loss_fraction >= self.packet_loss_ratio_target:
+ if measurement.loss_ratio >= self.packet_loss_ratio_target:
for _ in range(4 * zeros):
lossy_loads.append(measurement.target_tr)
if measurement.loss_count > 0:
Integrator assumes uniform distribution, but over different parameters.
Weight and likelihood are used interchangeably here anyway.
- Each trial has an offered load, a duration and a loss count.
- Fitting function is used to compute the average loss per second.
- Poisson distribution (with average loss per trial) is used
+ Each trial has an intended load, a sent count and a loss count
+ (probably counting unsent packets as loss, as they signal
+ the load is too high for the traffic generator).
+ The fitting function is used to compute the average loss rate.
+ Geometric distribution (with average loss per trial) is used
to get likelihood of one trial result, the overal likelihood
is a product of all trial likelihoods.
As likelihoods can be extremely small, logarithms are tracked instead.
+ The current implementation does not use direct loss rate
+ from the fitting function, as the input and output units may not match
+ (e.g. intended load in TCP transactions, loss in packets).
+ Instead, the expected average loss is scaled according to the number
+ of packets actually sent.
+
TODO: Copy ReceiveRateMeasurement from MLRsearch.
:param trace: A multiprocessing-friendly logging function (closure).
:rtype: multiprocessing.Connection
"""
+ boss_pipe_end, worker_pipe_end = multiprocessing.Pipe()
+ # Starting the worker first. Contrary to documentation
+ # https://docs.python.org/3/library/multiprocessing.html#multiprocessing.connection.Connection
+ # sending of large object without active listener on the other side
+ # results in a deadlock, not in a ValueError.
+ # See https://stackoverflow.com/questions/15137292/large-objects-and-multiprocessing-pipes-and-send
+ worker = multiprocessing.Process(
+ target=Integrator.try_estimate_nd,
+ args=(worker_pipe_end, 5.0, self.trace_enabled)
+ )
+ worker.daemon = True
+ worker.start()
+
+ # Only now it is safe to send the function to compute with.
def value_logweight_func(trace, x_mrr, x_spread):
"""Return log of critical rate and log of likelihood.
return value, logweight
dilled_function = dill.dumps(value_logweight_func)
- boss_pipe_end, worker_pipe_end = multiprocessing.Pipe()
- # Do not send yet, run the worker first to avoid a deadlock.
- # See https://stackoverflow.com/a/15716500
- worker = multiprocessing.Process(
- target=Integrator.try_estimate_nd,
- args=(worker_pipe_end, 10.0, self.trace_enabled)
- )
- worker.daemon = True
- worker.start()
boss_pipe_end.send(
(dimension, dilled_function, focus_tracker, max_samples)
)