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

[Commit slider] LLM bench support #28037

Merged
merged 2 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/plugins/intel_cpu/tools/commit_slider/utils/cfg.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"bmPerf" : "BenchmarkAppPerformanceMode",
"compareBlobs" : "CompareBlobsMode",
"ac" : "AccuracyCheckerMode",
"llmBench" : "LLMBenchMode",
"nop" : "NopMode"
},
"traversalMap" : {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"appCmd":"source {venvName}/bin/activate && cd {appPath} && python3.10 -m pip install --upgrade pip && python3.10 -m pip install openvino=={wheelVersion} openvino_genai=={wheelVersion} openvino_tokenizers=={wheelVersion} --find-links={precommitPath}wheels/ && python3.10 -m pip install -r requirements.txt && {cmd}",
"appPath" : "{appPath}",
"venvCfg":{
"venvEnabled":true,
"venvDir":"{workPath}/venv/",
"venvName":"tempVenv"
},
"commandList":[

],
"runConfig":{
"mode":"llmBench",
"traversal":"firstFailedVersion",
"perfAppropriateDeviation" : 0.05,
"commitList" : {
"getCommitListCmd" : "git log {c1}..{c2} --boundary --pretty=\"%h\""
}
},
"dlbConfig":{
"launchedAsJob":false,
"toolName":"",
"wheelVersionsMap":{

},
"commonPath":"{commitPath}",
"subPath":"{subPath}",
"appPath":"",
"appCmd":""
},
"cachedPathConfig":{
"enabled":true,
"scheme":"mandatory",
"passCmdList":false,
"changeAppPath":false,
"commonPath":"{commitPath}",
"subPath":"{subPath}",
"cashMap":{

}
},
"substitutionRules":[
{
"name":"precommitPath",
"enabled":true,
"type":"map",
"placeholder":"precommitPath",
"from":"$.cachedPathConfig.cashMap",
"to":"$.appCmd"
},
{
"name":"wheelVersion",
"enabled":true,
"type":"map",
"placeholder":"wheelVersion",
"from":"$.dlbConfig.wheelVersionsMap",
"to":"$.appCmd"
}
],
"subscriptions":[
{
"name":"wheelPathsMap",
"enabled":true
},
{
"name":"wheelVersionsMap",
"enabled":true
}
],
"verboseOutput" : true,
"checkIfBordersDiffer" : true
}
154 changes: 154 additions & 0 deletions src/plugins/intel_cpu/tools/commit_slider/utils/modes.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,160 @@ def getCommitInfo(self, commit):
ci=super().getCommitInfo(commit),
d=commit.perfRel)


class LLMBenchMode(Mode):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: please consider moving each mode to a separate file (since now modes.py is already quite cumbersome)

def __init__(self, cfg):
super().__init__(cfg)
self.perfRel = 0
self.createCash()

def isPerformanceBased(self):
return True

def prepareRun(self, list, cfg):
super().prepareRun(list, cfg)
sampleCommit = list[0]
sampleCommit = sampleCommit.replace('"', "")
self.commonLogger.info(
"Prepare sample commit - {commit}".format(commit=sampleCommit)
)
commitLogger = getCommitLogger(cfg, sampleCommit)
foundThroughput = 0
isCommitCashed, cashedThroughput = self.getCommitIfCashed(sampleCommit)
if isCommitCashed:
logMsg = "Cashed commit - {commit}".format(commit=sampleCommit)
self.commonLogger.info(logMsg)
commitLogger.info(logMsg)
foundThroughput = cashedThroughput
else:
handleCommit(sampleCommit, cfg)
output = fetchAppOutput(cfg, sampleCommit)
commitLogger.info(output)
foundThroughput = re.search(
self.outPattern, output, flags=re.MULTILINE
).group(1)
self.setCommitCash(sampleCommit, float(foundThroughput))
self.sampleThroughput = float(foundThroughput)
return list

def checkCfg(self, cfg):
super().checkCfg(cfg)
if not ("perfAppropriateDeviation" in cfg["runConfig"]):
raise CfgError("Appropriate deviation is not configured")
else:
self.apprDev = cfg["runConfig"]["perfAppropriateDeviation"]
if ("metric" in cfg["runConfig"]):
self.outPattern = self.specifyMetric(cfg["runConfig"]["metric"])
else:
self.outPattern = self.specifyMetric()


def specifyMetric(self, metric: str = "First token latency"):
if metric in [
"First token latency"]:
res = r"First token latency:\s*([0-9]*[.][0-9]*)\s*ms/token"
return res
raise CfgError("Metric {} is not supported".format(metric))

def preliminaryCheck(self, list, cfg):
# # model path checking - todo is necessary ?
# common if-degradation-exists check
super().preliminaryCheck(list, cfg)

# performance - specific check if results for borders are stable,
isLeftStable = not cfg["preliminaryCheckCfg"]["leftCheck"] or\
self.preliminaryStabilityCheck(list[0], cfg)
isRightStable = not cfg["preliminaryCheckCfg"]["rightCheck"] or\
self.preliminaryStabilityCheck(list[-1], cfg)
if (not isLeftStable or not isRightStable):
raise PreliminaryAnalysisError(
"{lCommit} is {lStable}, {rCommit} is {rStable}".format(
lCommit=list[0],
rCommit=list[-1],
lStable="stable" if isLeftStable else "unstable",
rStable="stable" if isRightStable else "unstable"
),
PreliminaryAnalysisError.PreliminaryErrType.UNSTABLE_APPLICATION
)

def compareCommits(self, lCommit: str, rCommit: str, cfg: map):
leftThroughput = self.getPseudoMetric(lCommit, cfg)
rightThroughput = self.getPseudoMetric(rCommit, cfg)
isBad, curRel = self.traversal.numericComparator(
leftThroughput, rightThroughput, self.apprDev
)
if isBad:
self.perfRel = curRel
curCommit = rCommit.replace('"', "")
commitLogger = getCommitLogger(cfg, curCommit)
commitLogger.info("Performance relation is {rel}".format(rel=curRel))
commitLogger.info(
"Commit is {status}".format(status=("bad" if isBad else "good"))
)
return isBad

def getPseudoMetric(self, commit, cfg):
commit = commit.replace('"', "")
curThroughput = 0
commitLogger = getCommitLogger(cfg, commit)
isCommitCashed, cashedThroughput = self.getCommitIfCashed(commit)
pc = Mode.CommitPath.PathCommit(
commit,
Mode.CommitPath.CommitState.DEFAULT
)
self.setOutputInfo(pc)
self.commitPath.accept(self.traversal, pc)
if isCommitCashed:
logMsg = "Cashed commit - {commit}".format(commit=commit)
self.commonLogger.info(logMsg)
commitLogger.info(logMsg)
curThroughput = cashedThroughput
else:
self.commonLogger.info("New commit: {commit}".format(
commit=commit)
)
handleCommit(commit, cfg)
output = fetchAppOutput(cfg, commit)
commitLogger.info(output)
foundThroughput = re.search(
self.outPattern, output, flags=re.MULTILINE
).group(1)
curThroughput = float(foundThroughput)
self.setCommitCash(commit, curThroughput)
return curThroughput

def preliminaryStabilityCheck(self, commit, cfg):
commit = commit.replace('"', "")
curThroughput = 0

self.commonLogger.info(
"Preliminary check of commit: {commit}".format(
commit=commit)
)
handleCommit(commit, cfg)
throughputList = []
dev = self.apprDev = cfg["runConfig"]["perfAppropriateDeviation"]
for i in range(cfg["preliminaryCheckCfg"]["tryCount"]):
output = fetchAppOutput(cfg, commit)
foundThroughput = re.search(
self.outPattern, output, flags=re.MULTILINE
).group(1)
curThroughput = float(foundThroughput)
throughputList.append(curThroughput)
resStable = checkStability(throughputList, dev)
if resStable:
self.setCommitCash(commit, curThroughput)
return resStable

def setOutputInfo(self, pathCommit):
pathCommit.perfRel = self.perfRel

def getCommitInfo(self, commit):
return "{ci}, perf. ratio = {d}".format(
ci=super().getCommitInfo(commit),
d=commit.perfRel)


class AccuracyCheckerMode(Mode):
def __init__(self, cfg):
super().__init__(cfg)
Expand Down
Loading