Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 451ae6c

Browse files
committed
Make temperature an adaptive counter like the rest
1 parent 5099356 commit 451ae6c

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
@@ -42,7 +42,7 @@ typedef struct {
4242

4343
typedef struct _exit_data {
4444
uint32_t target;
45-
int16_t temperature;
45+
uint16_t temperature;
4646
const struct _PyExecutorObject *executor;
4747
} _PyExitData;
4848

@@ -68,11 +68,10 @@ typedef int (*optimize_func)(
6868
struct _PyOptimizerObject {
6969
PyObject_HEAD
7070
optimize_func optimize;
71-
/* These thresholds are treated as signed so do not exceed INT16_MAX
72-
* Use INT16_MAX to indicate that the optimizer should never be called */
71+
/* Initial values for adaptive-style counters */
72+
uint16_t backedge_threshold;
7373
uint16_t resume_threshold;
7474
uint16_t side_threshold;
75-
uint16_t backedge_threshold;
7675
/* Data needed by the optimizer goes here, but is opaque to the VM */
7776
};
7877

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
@@ -4149,21 +4149,21 @@ dummy_func(
41494149
tier2 op(_COLD_EXIT, (--)) {
41504150
_PyExecutorObject *previous = (_PyExecutorObject *)tstate->previous_executor;
41514151
_PyExitData *exit = &previous->exits[oparg];
4152-
exit->temperature++;
41534152
PyCodeObject *code = _PyFrame_GetCode(frame);
41544153
_Py_CODEUNIT *target = _PyCode_CODE(code) + exit->target;
4155-
if (exit->temperature < (int32_t)tstate->interp->optimizer_side_threshold) {
4154+
if (!ADAPTIVE_COUNTER_IS_ZERO(exit->temperature)) {
4155+
DECREMENT_ADAPTIVE_COUNTER(exit->temperature);
41564156
GOTO_TIER_ONE(target);
41574157
}
41584158
_PyExecutorObject *executor;
41594159
if (target->op.code == ENTER_EXECUTOR) {
41604160
executor = code->co_executors->executors[target->op.arg];
41614161
Py_INCREF(executor);
4162-
} else {
4162+
}
4163+
else {
41634164
int optimized = _PyOptimizer_Optimize(frame, target, stack_pointer, &executor);
41644165
if (optimized <= 0) {
4165-
int32_t new_temp = -1 * tstate->interp->optimizer_side_threshold;
4166-
exit->temperature = (new_temp < INT16_MIN) ? INT16_MIN : new_temp;
4166+
exit->temperature = adaptive_counter_backoff(exit->temperature);
41674167
if (optimized < 0) {
41684168
Py_DECREF(previous);
41694169
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

@@ -183,10 +183,11 @@ _Py_SetOptimizer(PyInterpreterState *interp, _PyOptimizerObject *optimizer)
183183
interp->optimizer = optimizer;
184184
interp->optimizer_backedge_threshold = shift_and_offset_threshold(optimizer->backedge_threshold);
185185
interp->optimizer_resume_threshold = shift_and_offset_threshold(optimizer->resume_threshold);
186-
interp->optimizer_side_threshold = optimizer->side_threshold;
186+
interp->optimizer_side_threshold = shift_and_offset_threshold(optimizer->side_threshold);
187187
if (optimizer == &_PyOptimizer_Default) {
188188
assert(interp->optimizer_backedge_threshold == OPTIMIZER_UNREACHABLE_THRESHOLD);
189189
assert(interp->optimizer_resume_threshold == OPTIMIZER_UNREACHABLE_THRESHOLD);
190+
assert(interp->optimizer_side_threshold == OPTIMIZER_UNREACHABLE_THRESHOLD);
190191
}
191192
return old;
192193
}
@@ -941,9 +942,11 @@ make_executor_from_uops(_PyUOpInstruction *buffer, const _PyBloomFilter *depende
941942
OPT_HIST(length, optimized_trace_length_hist);
942943

943944
/* Initialize exits */
945+
PyInterpreterState *interp = _PyInterpreterState_GET();
944946
for (int i = 0; i < exit_count; i++) {
945947
executor->exits[i].executor = &COLD_EXITS[i];
946-
executor->exits[i].temperature = 0;
948+
executor->exits[i].temperature =
949+
adaptive_counter_bits(interp->optimizer_side_threshold, 4); // TODO: Constantify
947950
}
948951
int next_exit = exit_count-1;
949952
_PyUOpInstruction *dest = (_PyUOpInstruction *)&executor->trace[length-1];
@@ -1104,11 +1107,11 @@ PyUnstable_Optimizer_NewUOpOptimizer(void)
11041107
return NULL;
11051108
}
11061109
opt->optimize = uop_optimize;
1107-
opt->resume_threshold = OPTIMIZER_UNREACHABLE_THRESHOLD;
11081110
// Need a few iterations to settle specializations,
11091111
// and to ammortize the cost of optimization.
1110-
opt->side_threshold = 16;
11111112
opt->backedge_threshold = 16;
1113+
opt->resume_threshold = OPTIMIZER_UNREACHABLE_THRESHOLD;
1114+
opt->side_threshold = 16;
11121115
return (PyObject *)opt;
11131116
}
11141117

@@ -1196,9 +1199,9 @@ PyUnstable_Optimizer_NewCounter(void)
11961199
return NULL;
11971200
}
11981201
opt->base.optimize = counter_optimize;
1202+
opt->base.backedge_threshold = 0;
11991203
opt->base.resume_threshold = OPTIMIZER_UNREACHABLE_THRESHOLD;
12001204
opt->base.side_threshold = OPTIMIZER_UNREACHABLE_THRESHOLD;
1201-
opt->base.backedge_threshold = 0;
12021205
opt->count = 0;
12031206
return (PyObject *)opt;
12041207
}
@@ -1365,7 +1368,7 @@ _Py_ExecutorClear(_PyExecutorObject *executor)
13651368
for (uint32_t i = 0; i < executor->exit_count; i++) {
13661369
Py_DECREF(executor->exits[i].executor);
13671370
executor->exits[i].executor = &COLD_EXITS[i];
1368-
executor->exits[i].temperature = INT16_MIN;
1371+
executor->exits[i].temperature = OPTIMIZER_UNREACHABLE_THRESHOLD;
13691372
}
13701373
_Py_CODEUNIT *instruction = &_PyCode_CODE(code)[executor->vm_data.index];
13711374
assert(instruction->op.code == ENTER_EXECUTOR);

0 commit comments

Comments
 (0)