Skip to content

Commit 8c74dfa

Browse files
committed
Make temperature an adaptive counter like the rest
1 parent e7e819b commit 8c74dfa

File tree

5 files changed

+25
-24
lines changed

5 files changed

+25
-24
lines changed

Include/cpython/optimizer.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ static inline uint16_t uop_get_error_target(const _PyUOpInstruction *inst)
8989

9090
typedef struct _exit_data {
9191
uint32_t target;
92-
int16_t temperature;
92+
uint16_t temperature;
9393
const struct _PyExecutorObject *executor;
9494
} _PyExitData;
9595

@@ -115,11 +115,10 @@ typedef int (*optimize_func)(
115115
struct _PyOptimizerObject {
116116
PyObject_HEAD
117117
optimize_func optimize;
118-
/* These thresholds are treated as signed so do not exceed INT16_MAX
119-
* Use INT16_MAX to indicate that the optimizer should never be called */
118+
/* Initial values for adaptive-style counters */
119+
uint16_t backedge_threshold;
120120
uint16_t resume_threshold;
121121
uint16_t side_threshold;
122-
uint16_t backedge_threshold;
123122
/* Data needed by the optimizer goes here, but is opaque to the VM */
124123
};
125124

Include/internal/pycore_interp.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,9 @@ struct _is {
239239
_PyOptimizerObject *optimizer;
240240
_PyExecutorObject *executor_list_head;
241241

242-
/* These two values are shifted and offset to speed up check in JUMP_BACKWARD */
243-
uint32_t optimizer_resume_threshold;
242+
/* These three values are shifted and offset to speed up check in JUMP_BACKWARD */
244243
uint32_t optimizer_backedge_threshold;
245-
244+
uint32_t optimizer_resume_threshold;
246245
uint16_t optimizer_side_threshold;
247246

248247
_rare_events rare_events;

Python/bytecodes.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4157,21 +4157,21 @@ dummy_func(
41574157
tier2 op(_COLD_EXIT, (--)) {
41584158
_PyExecutorObject *previous = (_PyExecutorObject *)tstate->previous_executor;
41594159
_PyExitData *exit = &previous->exits[oparg];
4160-
exit->temperature++;
41614160
PyCodeObject *code = _PyFrame_GetCode(frame);
41624161
_Py_CODEUNIT *target = _PyCode_CODE(code) + exit->target;
4163-
if (exit->temperature < (int32_t)tstate->interp->optimizer_side_threshold) {
4162+
if (!ADAPTIVE_COUNTER_IS_ZERO(exit->temperature)) {
4163+
DECREMENT_ADAPTIVE_COUNTER(exit->temperature);
41644164
GOTO_TIER_ONE(target);
41654165
}
41664166
_PyExecutorObject *executor;
41674167
if (target->op.code == ENTER_EXECUTOR) {
41684168
executor = code->co_executors->executors[target->op.arg];
41694169
Py_INCREF(executor);
4170-
} else {
4170+
}
4171+
else {
41714172
int optimized = _PyOptimizer_Optimize(frame, target, stack_pointer, &executor);
41724173
if (optimized <= 0) {
4173-
int32_t new_temp = -1 * tstate->interp->optimizer_side_threshold;
4174-
exit->temperature = (new_temp < INT16_MIN) ? INT16_MIN : new_temp;
4174+
exit->temperature = adaptive_counter_backoff(exit->temperature);
41754175
if (optimized < 0) {
41764176
Py_DECREF(previous);
41774177
tstate->previous_executor = Py_None;

Python/executor_cases.c.h

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/optimizer.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ PyTypeObject _PyDefaultOptimizer_Type = {
125125
static _PyOptimizerObject _PyOptimizer_Default = {
126126
PyObject_HEAD_INIT(&_PyDefaultOptimizer_Type)
127127
.optimize = never_optimize,
128-
.resume_threshold = OPTIMIZER_UNREACHABLE_THRESHOLD,
129128
.backedge_threshold = OPTIMIZER_UNREACHABLE_THRESHOLD,
129+
.resume_threshold = OPTIMIZER_UNREACHABLE_THRESHOLD,
130130
.side_threshold = OPTIMIZER_UNREACHABLE_THRESHOLD,
131131
};
132132

@@ -189,10 +189,11 @@ _Py_SetOptimizer(PyInterpreterState *interp, _PyOptimizerObject *optimizer)
189189
interp->optimizer = optimizer;
190190
interp->optimizer_backedge_threshold = shift_and_offset_threshold(optimizer->backedge_threshold);
191191
interp->optimizer_resume_threshold = shift_and_offset_threshold(optimizer->resume_threshold);
192-
interp->optimizer_side_threshold = optimizer->side_threshold;
192+
interp->optimizer_side_threshold = shift_and_offset_threshold(optimizer->side_threshold);
193193
if (optimizer == &_PyOptimizer_Default) {
194194
assert(interp->optimizer_backedge_threshold == OPTIMIZER_UNREACHABLE_THRESHOLD);
195195
assert(interp->optimizer_resume_threshold == OPTIMIZER_UNREACHABLE_THRESHOLD);
196+
assert(interp->optimizer_side_threshold == OPTIMIZER_UNREACHABLE_THRESHOLD);
196197
}
197198
return old;
198199
}
@@ -1103,10 +1104,12 @@ make_executor_from_uops(_PyUOpInstruction *buffer, int length, const _PyBloomFil
11031104
}
11041105

11051106
/* Initialize exits */
1107+
PyInterpreterState *interp = _PyInterpreterState_GET();
11061108
assert(exit_count < COLD_EXIT_COUNT);
11071109
for (int i = 0; i < exit_count; i++) {
11081110
executor->exits[i].executor = &COLD_EXITS[i];
1109-
executor->exits[i].temperature = 0;
1111+
executor->exits[i].temperature =
1112+
adaptive_counter_bits(interp->optimizer_side_threshold, 4); // TODO: Constantify
11101113
}
11111114
int next_exit = exit_count-1;
11121115
_PyUOpInstruction *dest = (_PyUOpInstruction *)&executor->trace[length];
@@ -1288,11 +1291,11 @@ PyUnstable_Optimizer_NewUOpOptimizer(void)
12881291
return NULL;
12891292
}
12901293
opt->optimize = uop_optimize;
1291-
opt->resume_threshold = OPTIMIZER_UNREACHABLE_THRESHOLD;
12921294
// Need a few iterations to settle specializations,
12931295
// and to ammortize the cost of optimization.
1294-
opt->side_threshold = 16;
12951296
opt->backedge_threshold = 16;
1297+
opt->resume_threshold = OPTIMIZER_UNREACHABLE_THRESHOLD;
1298+
opt->side_threshold = 16;
12961299
return (PyObject *)opt;
12971300
}
12981301

@@ -1382,9 +1385,9 @@ PyUnstable_Optimizer_NewCounter(void)
13821385
return NULL;
13831386
}
13841387
opt->base.optimize = counter_optimize;
1388+
opt->base.backedge_threshold = 0;
13851389
opt->base.resume_threshold = OPTIMIZER_UNREACHABLE_THRESHOLD;
13861390
opt->base.side_threshold = OPTIMIZER_UNREACHABLE_THRESHOLD;
1387-
opt->base.backedge_threshold = 0;
13881391
opt->count = 0;
13891392
return (PyObject *)opt;
13901393
}
@@ -1551,7 +1554,7 @@ _Py_ExecutorClear(_PyExecutorObject *executor)
15511554
for (uint32_t i = 0; i < executor->exit_count; i++) {
15521555
Py_DECREF(executor->exits[i].executor);
15531556
executor->exits[i].executor = &COLD_EXITS[i];
1554-
executor->exits[i].temperature = INT16_MIN;
1557+
executor->exits[i].temperature = OPTIMIZER_UNREACHABLE_THRESHOLD;
15551558
}
15561559
_Py_CODEUNIT *instruction = &_PyCode_CODE(code)[executor->vm_data.index];
15571560
assert(instruction->op.code == ENTER_EXECUTOR);

0 commit comments

Comments
 (0)