У меня есть стандартная реализация DFS в моем коде, которая использует динамически выделенный стек для каждого вызова.Использование стека программ в реализации DFS
Я называю эту функцию много. Часто на небольших узлах (200-1000), но иногда есть большой подключенный компонент с миллионом узлов и более.
Профилировщик показывает, что значительное количество вычислительного времени теряется при распределении стека. Я хочу попытаться повторно использовать существующую память (например, стек вызовов). Однако функция должна оставаться потокобезопасной.
Есть ли эффективный способ динамического использования стека вызовов, не делая функцию рекурсивной?
Моя лучшая идея до сих пор заключалась в том, чтобы сделать функцию рекурсивной с дополнительным аргументом, который удваивает размер автоматического стека при каждом последующем вызове.
Псевда C:
void dfs(size_t stack_length, void * graph, graphnode_t start_node) {
graphnode_t stack[stack_length];
size_t stack_size = 0;
for (all nodes) {
// do something useful
if (stack_size < stack_length) {
stack[stack_size++] = new_node;
} else {
dfs(stack_length * 2, graph, new_node);
}
}
}
Я думал о глобальной статической переменной. Но именно здесь я столкнулся с конфликтами с безопасностью потоков. Каждый поток должен запускать свои собственные независимые dfs с собственным личным стеком узлов для работы. Код должен быть реентерабельным. Я подумал о создании стека за поток, но тогда мне придется избавиться от него, когда потоки погибнут. –
Создание отдельного частного массива в потоке довольно легко сделать, и избавиться от него при завершении потока также очень просто. Если 'dfs' не является рекурсивным и может стоять как« поток », вы должны выделить начальный массив вперед как локальный указатель/размер, изменить функцию перераспределения, чтобы принять адреса из них, и очистить в конце функции. (Я буду обновлять свой ответ, чтобы отразить это.) Есть ли что-то, что делает вас устойчивыми к этой возможности? – mah
Примечание. Вы не указали, какую резьбу вы используете. Я изменил функцию 'dfs', чтобы она выглядела как _is_ поток, и, поскольку многие потоковые пакеты работают, получает только один аргумент' void * ', поэтому я создал структуру, указывающую на ваши реальные аргументы. – mah