Простой доступ к вектору C ++ со смещением индекса - PullRequest
0 голосов
/ 17 июня 2020

У меня есть куча данных элемента, например, 1000 данных с «тегом» были начаты с целого числа 9, поэтому последний тег был 1008. Я бы создал вектор, достаточно простой для доступа к определенному тегу c с помощью вектора index,

std::vector<double> element_data(1009)

, но если тег начинается с более высокого целого числа, это приведет к появлению мусора с 0 до индекса начального тега (смещения).

Как решить эту проблему? Спасибо.

Ответы [ 2 ]

1 голос
/ 17 июня 2020

std::vector - это контейнер, в котором хранятся элементы, проиндексированные от 0. Если 1000 - это размер ваших данных, который известен во время компиляции, вы можете улучшить дизайн, используя вместо этого std::array. Это то, что мы знаем, не вдаваясь в подробности вашего приложения.

Давайте вернемся к вашему вопросу. У вас есть объект, у которого есть «теги». Похоже, что эти теги являются последовательными целыми числами, и вы используете их как числовые c значения. Этот объект не совсем то, что есть вектор / массив. Это то, что хранит данные в любом контейнере и предоставляет вам доступ на основе значения тега. Почему бы не использовать композицию?

class TaggedData
{
public:
    int& operator [](size_t tag) { return array[tag - 9]; }
    const int& operator [](size_t tag) const { return array[tag - 9]; }
private:
    std::array<int, 1000> array;
};

Это простая реализация, вы можете улучшить ее любым способом. Например, вы можете использовать следующие параметры шаблона magi c numbers:

template<size_t N, size_t OFFSET>
class TaggedData
{
public:
    int& operator [](size_t tag) { return array[tag - OFFSET]; }
    const int& operator [](size_t tag) const { return array[tag - OFFSET]; }
private:
    std::array<int, N> array;
};

Вы также можете сделать фактический контейнер параметром шаблона. Позже вы можете обнаружить, что теги не являются последовательными или даже не целыми числами.

Вывод такой: только вы знаете свою задачу, детали бизнес-логи c, планы на будущее и т.д. поэтому вам нужно принять решение, основываясь на этом.

0 голосов
/ 17 июня 2020

Стоимость операции вычитания будет очень трудно измерить. Вы в основном гадаете, не понимая, что стоит дорого, а что нет. На современном оборудовании целочисленная арифметика c, кроме деления, по сути бесплатна. Если у вас есть проблема с производительностью, вы должны измерить ее, попробовать решения, а затем подтвердить - опять же измерением - что ваше решение что-то сделало. В противном случае вы с вероятностью 99,999999% полностью обманете себя и потратите время на дела, которые не только не улучшают производительность, но обычно также ухудшают качество кода.

Опять же: если вы думаете, что у вас проблемы с производительностью, у вас должен быть способ протестировать его, включить тесты в набор тестов, чтобы избежать снижения производительности, а затем работать оттуда. По крайней мере, вам нужно иметь возможность воспроизводить результаты тестов во время разработки.

Итак, если вы думаете, что хотите что-то сделать «из-за производительности», вам нужно оба имеют своего рода аргумент относительно того, почему вы считаете, что производительность играет роль, а также имеют план того, как ее измерить. В противном случае вы относитесь ко всему этому так, как если бы это был какой-то непробиваемый маг c, и ваши заклинания просто таковы: храбрый ни на что не пытается. Не используйте go этот маршрут.

На современных платформах вам дорого обходятся промахи в кэше, неверные предсказания переходов и зависимости данных. Зависимости не позволяют использовать параллельную обработку, присущую современным ядрам, два других просто замедляют работу. Если вам нужны некоторые практические правила, вы можете думать, что промах в кэше L1 стоит больше, чем целочисленное деление. Полный промах в кэше, когда строку кэша необходимо вытащить из ОЗУ, - это достаточно времени, чтобы отобразить контур глифа шрифта TrueType, когда код для этого имеет горячие кеши и просто радостно пыхтит, выполняя вычисления с плавающей запятой. И между прочим: деление с плавающей запятой обычно дешевле, чем целочисленное деление (по крайней мере, на современных платформах Intel).

Так что ни один из этих вещей не является полностью интуитивным без хорошего опыта в современном компьютерная архитектура.

Еще один способ думать о производительности: если в течение следующего года вы потратите больше времени на «исправление» производительности, чем в 1 / 1000–1 / 1000000 раз от сэкономленного вами времени выполнения ЦП, вы просто выбрасываете деньги - ничто из того, что вы сэкономите процессорное время в таких масштабах, не окупит ваши затраты на работу над проблемой. Если вы потратите час на исправление производительности, это лучше сэкономит вам от тысячи до миллиона часов работы процессора в следующем году, или вы добровольно жертвуете свое время на безнадежное дело: добровольчество, потому что время, которое вы тратите на работу, не имеет стоит (кроме, возможно, самообразования или приобретения опыта), и это безнадежное дело, потому что 1000 часов процессора почти бесплатны. Даже в 1000 раз больше часов процессора может стоить меньше часа вашего времени, если, например, они оплачиваются пользователями (т.е. вы запускаете какой-то код в браузере пользователя, а не на сервере, за который вам выставлен счет).

Что касается создания «мусора» со смещением 0: вы только что сказали, что не используете это смещение ни для чего, так почему вы беспокоитесь, какое значение там хранится? Вы не должны это читать, верно? Вы должны рассказать нам всю историю: как и когда вы записываете значения в вектор, как вы их читаете и используете. В противном случае мне трудно представить, почему вы воспринимаете то, что вы описываете как проблему. Если вы говорите, что используете диапазон индексов, например, от 9 до 1009, тогда кого волнует, что находится под индексом 0. Проблема решена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...