Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Demo for visualize #141

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion .github/workflows/python-package-genai.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
fail-fast: false
matrix:
os: ["ubuntu-22.04"]
python-version: ["3.8", "3.10"]
python-version: ["3.10"]

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion genai-perf/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ genai-perf --help
Since GenAI-Perf depends on Perf Analyzer,
you'll need to install the Perf Analyzer binary:

### Install Perf Analyzer (Ubuntu, Python 3.8+)
### Install Perf Analyzer (Ubuntu, Python 3.10+)

**NOTE**: you must already have CUDA 12 installed
(checkout the [CUDA installation guide](https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html)).
Expand Down
98 changes: 98 additions & 0 deletions genai-perf/genai_perf/checkpoint/checkpoint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Copyright 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# 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.

import json
import os
from dataclasses import dataclass

from genai_perf.config.input.config_command import ConfigCommand
from genai_perf.config.run.results import Results
from genai_perf.exceptions import GenAIPerfException
from genai_perf.types import CheckpointObject


@dataclass(frozen=True)
class CheckpointDefaults:
FILENAME = "checkpoint.json"


@dataclass
class Checkpoint:
"""
Contains the methods necessary for reading and writing GenAI-Perf
state to a file so that stateful subcommands (such as Optimize or
Analyze) can resume or continue (ex: running Analyze then Visualize)
"""

config: ConfigCommand

# Every top-level class that needs to store state is passed in
results: Results

def __post_init__(self):
self._create_class_from_checkpoint()

###########################################################################
# Read/Write Methods
###########################################################################
def create_checkpoint_object(self) -> None:
state_dict = {"Results": self.results.create_checkpoint_object()}

checkpoint_file_path = self._create_checkpoint_file_path()
with open(checkpoint_file_path, "w") as checkpoint_file:
json.dump(state_dict, checkpoint_file, default=checkpoint_encoder)

def _create_class_from_checkpoint(self) -> None:
checkpoint_file_path = self._create_checkpoint_file_path()

if os.path.isfile(checkpoint_file_path):
self.checkpoint_exists = True
try:
with open(checkpoint_file_path, "r") as checkpoint_file:
checkpoint_json = json.load(checkpoint_file)
self._state: CheckpointObject = {
"Results": Results.create_class_from_checkpoint(
checkpoint_json["Results"]
)
}

except EOFError:
raise (
GenAIPerfException(
f"Checkpoint file {checkpoint_file} is"
" empty or corrupted. Delete it and rerun GAP"
)
)
else:
self.checkpoint_exists = False
self._state = {}

def _create_checkpoint_file_path(self) -> str:
checkpoint_file_path = os.path.join(
self.config.checkpoint_directory, CheckpointDefaults.FILENAME
)

return checkpoint_file_path


###########################################################################
# Encoder
###########################################################################
def checkpoint_encoder(obj):
if isinstance(obj, bytes):
return obj.decode("utf-8")
elif hasattr(obj, "create_checkpoint_object"):
return obj.create_checkpoint_object()
else:
return obj.__dict__
94 changes: 94 additions & 0 deletions genai-perf/genai_perf/config/generate/genai_perf_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Copyright 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# 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.

from copy import deepcopy
from dataclasses import dataclass

from genai_perf.config.generate.search_parameter import SearchUsage
from genai_perf.config.input.config_command import (
ConfigCommand,
ConfigInput,
ConfigOutputTokens,
ConfigSyntheticTokens,
)
from genai_perf.types import CheckpointObject, ModelObjectiveParameters


@dataclass
class GenAIPerfConfig:
"""
Creates a config that can be used by be
used by other modules to configure the various
options of GenAI-Perf
"""

def __init__(
self,
config: ConfigCommand,
model_objective_parameters: ModelObjectiveParameters,
):
self._set_options_based_on_config(config)
self._set_options_based_on_objective(model_objective_parameters)

###########################################################################
# Set Options Methods
###########################################################################
def _set_options_based_on_config(self, config: ConfigCommand) -> None:
self.input: ConfigInput = config.input
self.output_tokens: ConfigOutputTokens = config.output_tokens

def _set_options_based_on_objective(
self, model_objective_parameters: ModelObjectiveParameters
) -> None:
for objective in model_objective_parameters.values():
for name, parameter in objective.items():
if parameter.usage == SearchUsage.RUNTIME_GAP:
if hasattr(self.input, name):
self.input.__setattr__(
name, parameter.get_value_based_on_category()
)

###########################################################################
# Checkpoint Methods
###########################################################################
def create_checkpoint_object(self) -> CheckpointObject:
"""
Converts the class data into a dictionary that can be written to
the checkpoint file
"""
genai_perf_config_dict = deepcopy(self.__dict__)

return genai_perf_config_dict

@classmethod
def create_class_from_checkpoint(
cls, genai_perf_config_dict: CheckpointObject
) -> "GenAIPerfConfig":
"""
Takes the checkpoint's representation of the class and creates (and populates)
a new instance of a GenAIPerfConfig
"""
genai_perf_config = GenAIPerfConfig(
config=ConfigCommand([""]),
model_objective_parameters={},
)
genai_perf_config.input = ConfigInput(**genai_perf_config_dict["input"])
genai_perf_config.input.synthetic_tokens = ConfigSyntheticTokens(
**genai_perf_config_dict["input"]["synthetic_tokens"]
)
genai_perf_config.output_tokens = ConfigOutputTokens(
**genai_perf_config_dict["output_tokens"]
)

return genai_perf_config
51 changes: 51 additions & 0 deletions genai-perf/genai_perf/config/generate/objective_parameter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Copyright 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# 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.

from dataclasses import dataclass
from enum import Enum, auto
from typing import Any, Dict, TypeAlias

from genai_perf.config.generate.search_parameter import SearchUsage
from genai_perf.exceptions import GenAIPerfException


class ObjectiveCategory(Enum):
INTEGER = auto()
EXPONENTIAL = auto()
STR = auto()


ObjectiveParameters: TypeAlias = Dict[str, "ObjectiveParameter"]


@dataclass
class ObjectiveParameter:
"""
A dataclass that holds information about a configuration's objective parameter
"""

usage: SearchUsage
category: ObjectiveCategory
value: Any

def get_value_based_on_category(self) -> Any:
if (
self.category == ObjectiveCategory.INTEGER
or self.category == ObjectiveCategory.STR
):
return self.value
elif self.category == ObjectiveCategory.EXPONENTIAL:
return 2**self.value

raise GenAIPerfException(f"{self.category} is not a known ObjectiveCategory")
Loading
Loading