Skip to content

Commit

Permalink
update fixed rate profile generator, add tests, set up initial execut…
Browse files Browse the repository at this point in the history
…or test
  • Loading branch information
DaltheCow committed Jul 9, 2024
1 parent bf72422 commit 98f79c4
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 20 deletions.
21 changes: 14 additions & 7 deletions src/guidellm/executor/profile_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,30 +69,37 @@ def next_profile(

@ProfileGenerator.register_generator(ProfileGenerationModes.FIXED)
class FixedRateProfileGenerator(ProfileGenerator):
def __init__(self, rate: List[float], rate_type: str, **kwargs):
def __init__(self, rate_type: str, rate: Optional[List[float]] = None, **kwargs):
super().__init__(ProfileGenerationModes.FIXED)
if rate_type == "synchronous" and len(rate) > 0:
if rate_type == "synchronous" and rate and len(rate) > 0:
raise ValueError("custom rates are not supported in synchronous mode")
self._rates = rate
self._rate_index = 0
self._generated = False
self._rate_type = rate_type

def next_profile(
self, current_report: TextGenerationBenchmarkReport
) -> Optional[Profile]:
if self._rate_index >= len(self._rates):
return None
if self._rate_type == "synchronous":
if self._generated:
return None

current_rate = self._rates[self._rate_index]
self._rate_index += 1
self._generated = True

if self._rate_type == "synchronous":
return Profile(
load_gen_mode=LoadGenerationModes.SYNCHRONOUS, load_gen_rate=None
)

if self._rate_type in {"constant", "poisson"}:
if self._rate_index >= len(self._rates):
return None

current_rate = self._rates[self._rate_index]
self._rate_index += 1

load_gen_mode = RateTypeLoadGenModeMap[self._rate_type]

return Profile(
load_gen_mode=load_gen_mode, load_gen_rate=current_rate
)
Expand Down
17 changes: 17 additions & 0 deletions tests/unit/executor/test_executor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from unittest.mock import MagicMock
from src.guidellm.backend.base import Backend
from src.guidellm.executor.executor import Executor
from src.guidellm.request.base import RequestGenerator

def test_executor_creation():
mock_request_generator = MagicMock(spec=RequestGenerator)
mock_backend = MagicMock(spec=Backend)
rate_type = "sweep"
profile_args = None
max_requests = None,
max_duration = None,
executor = Executor(mock_request_generator, mock_backend, rate_type, profile_args, max_requests, max_duration);
assert executor.request_generator == mock_request_generator
assert executor.backend == mock_backend
assert executor.max_requests == max_requests
assert executor.max_duration == max_duration
54 changes: 41 additions & 13 deletions tests/unit/executor/test_profile_generator.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import pytest

from unittest.mock import MagicMock
from guidellm.executor import (ProfileGenerator, FixedRateProfileGenerator, SweepProfileGenerator)
from src.guidellm.core.result import TextGenerationBenchmarkReport
from src.guidellm.scheduler.load_generator import LoadGenerationModes

def test_invalid_profile_generation_mode_error():
rate = [1]
Expand All @@ -10,19 +12,45 @@ def test_invalid_profile_generation_mode_error():
ProfileGenerator.create_generator(profile_mode, **({ "rate": rate, "rate_type": rate_type}))

def test_sweep_profile_generator_creation():
profile = ProfileGenerator.create_generator("sweep", **({}))
assert isinstance(profile, SweepProfileGenerator)
assert profile._sync_run == False
assert profile._max_found == False
assert profile._pending_rates == None
assert profile._pending_rates == None
profile_generator = ProfileGenerator.create_generator("sweep", **({}))
assert isinstance(profile_generator, SweepProfileGenerator)
assert profile_generator._sync_run == False
assert profile_generator._max_found == False
assert profile_generator._pending_rates == None
assert profile_generator._pending_rates == None

def test_fixed_rate_profile_generator_creation():
rate = [1]
rate_type = "constant"
profile = ProfileGenerator.create_generator("fixed_rate", **({ "rate": rate, "rate_type": rate_type}))
assert isinstance(profile, FixedRateProfileGenerator)
assert profile._rates == rate
assert profile._rate_type == rate_type
assert profile._rate_index == 0
assert profile._rate_index == 0
profile_generator = ProfileGenerator.create_generator("fixed_rate", **({ "rate": rate, "rate_type": rate_type}))
assert isinstance(profile_generator, FixedRateProfileGenerator)
assert profile_generator._rates == rate
assert profile_generator._rate_type == rate_type
assert profile_generator._rate_index == 0
assert profile_generator._rate_index == 0

def test_synchronous_mode_rate_list_error():
rate = [1]
rate_type = "synchronous"
with pytest.raises(ValueError, match="custom rates are not supported in synchronous mode"):
ProfileGenerator.create_generator("fixed_rate", **({ "rate": rate, "rate_type": rate_type}))

def test_next_profile_with_multiple_rates():
rates = [1, 2]
rate_type = "constant"
profile_generator = ProfileGenerator.create_generator("fixed_rate", **({ "rate": rates, "rate_type": rate_type}))
mock_report = MagicMock(spec=TextGenerationBenchmarkReport)
for rate in rates:
current_profile = profile_generator.next_profile(mock_report)
assert current_profile.load_gen_rate == rate
assert current_profile.load_gen_mode.name == LoadGenerationModes.CONSTANT.name
assert profile_generator.next_profile(mock_report) == None

def test_next_profile_with_sync_mode():
rate_type = "synchronous"
profile_generator = ProfileGenerator.create_generator("fixed_rate", **({ "rate_type": rate_type}))
mock_report = MagicMock(spec=TextGenerationBenchmarkReport)
current_profile = profile_generator.next_profile(mock_report)
assert current_profile.load_gen_rate == None
assert current_profile.load_gen_mode.name == LoadGenerationModes.SYNCHRONOUS.name
assert profile_generator.next_profile(mock_report) == None

0 comments on commit 98f79c4

Please sign in to comment.