У меня есть некоторые структуры данных:
all_unordered_m
большой вектор, содержащий все строки, в которых я нуждаюсь (все отличающиеся)ordered_m
маленький вектор, содержащий индексы подмножества строк (все отличающиеся) в бывшем вектореposition_m
отображает индексы объектов от первого вектора до их положения во втором. string_after(index, reverse)
метод возвращает строку, на которую ссылается ordered_m после all_unordered_m[index]
.
ordered_m
считается круговым, и исследуется в естественном или обратном порядке в зависимости от второго параметра.
Код - что-то как следующее:
struct ordered_subset {
// [...]
std::vector<std::string>& all_unordered_m; // size = n >> 1
std::vector<size_t> ordered_m; // size << n
std::tr1::unordered_map<size_t, size_t> position_m;
const std::string&
string_after(size_t index, bool reverse) const
{
size_t pos = position_m.find(index)->second;
if(reverse)
pos = (pos == 0 ? orderd_m.size() - 1 : pos - 1);
else
pos = (pos == ordered.size() - 1 ? 0 : pos + 1);
return all_unordered_m[ordered_m[pos]];
}
};
Учитывая, что:
Как я могу убыстриться string_after
метод, который называют миллиардами времен и съедает выше на приблизительно 10% времени выполнения?
Править: Я попытался делать position_m
a vector
вместо a unordered_map
и использование следующего метода для предотвращения переходов:
string_after(size_t index, int direction) const
{
return all_unordered_m[ordered_m[
(ordered_m.size()+position_m[index]+direction)%ordered_m.size()]];
}
Изменение в position_m, кажется, является самым эффективным (я не уверен, что устранение ответвлений имело любое значение, я испытываю желание сказать, что код более компактен, но одинаково эффективен с тем отношением).
поиск вектора
быстро выполняется. Вызовы size ()
и простая арифметика стремительно развиваются. Для сравнения, поиск по карте
медленный, как мертвая черепаха с бетонным блоком на спине. Я часто видел, как они становятся узким местом в таком простом коде, как этот.
Вместо этого вы можете попробовать unordered_map
из TR1 или C ++ 0x (заменяющая хеш-таблица map
) и посмотреть, имеет ли это значение.
Что ж, в таких случаях (небольшая функция, которая часто вызывается) каждая ветвь может быть очень дорогой. На ум приходят две вещи.
reverse
и сделать его двумя отдельными методами? Это имеет смысл только в том случае, если это не просто подталкивает выражение if
к вызывающему коду. pos
: pos = (pos + 1)% orders_m.size ()
(это для прямого случая). Это работает, только если вы уверены, что pos
никогда не переполняется при его увеличении. В общем, в таких случаях старайтесь заменять ветвления арифметическими операциями, это может значительно ускорить процесс.