Должен ли я сделать эти векторы классы или структуры в C # - PullRequest
8 голосов
/ 19 апреля 2010

Я создаю библиотеку геометрии в C #, и мне понадобятся следующие неизменяемые типы:

  • Vector2f (2 float с - 8 байт)
  • Vector2d (2 double с - 16 байтов)
  • Vector3f (3 float с - 12 байт)
  • Vector3d (3 double с - 24 байта)
  • Vector4f (4 float с - 16 байтов)
  • Vector4d (4 double с - 32 байта)

Я пытаюсь определить, делают ли они структуры или классы. MSDN предлагает использовать структуру только в том случае, если размер будет не более 16 байт. Эта ссылка, похоже, относится к 2005 году. Является ли 16 байтов максимальным рекомендуемым размером?

Я уверен, что использование структур для векторов float будет более эффективным, чем использование класса, но что мне делать с векторами double? Должен ли я сделать их структуры также согласованными, или я должен сделать их классами?

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

Ответы [ 8 ]

8 голосов
/ 19 апреля 2010

Microsoft XNA Framework использует структуры для типов данных Vector2 / 3 / 4 . Они содержат поля типа float. Я не вижу в этом ничего плохого; использование полей типа double не должно иметь большого значения.

4 голосов
/ 19 апреля 2010

Неизменяемые структуры - хороший выбор. Рекомендации по размеру MSDN самые слабые, 32 байта не очень большие.

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

Хорошая параллель - новые структуры Complex и BigInteger в dotNet 4

4 голосов
/ 19 апреля 2010

Я бы обычно делал типы, подобные этим структурам. Структуры с большей вероятностью размещаются в стеке, и если вы используете с ними массивы, вы можете получить гораздо более хорошую производительность, чем, скажем, если бы вы использовали List <> объектов. Пока вы избегаете операций, которые приведут к тому, что ваши векторные классы будут упакованы, структура, как правило, будет иметь более высокую производительность.

3 голосов
/ 19 апреля 2010

Структуры, безусловно. Зачем? Ну, это отчасти чувство, я думаю, вектор просто чувствует и ведет себя как значение .

Rico Mariani здесь приводит некоторые причины, по которым типы значений были выбраны для определенных типов для API (я не думаю, что речь идет о XNA).

И хотя здесь фактор эффективности, я не думаю, что речь идет о сборке мусора, а о плотности данных , как говорит Рико. Скажем, у вас также есть тип Vertex, который содержит два Vector3 s: a Vector3 для нормалей и Vector3 для мировых координат. Если вы создали классы этих типов, то массив из 100 Vertex элементов будет состоять из:

  • 100 * 8 байт (я полагаю, 8 байтов - это издержки класса в памяти, 4 байта для заголовка типа и 4 байта для чего-то еще, дескриптор GC?)
  • 100 * 4 байта (для указателей в массиве на элементы Vertex)
  • 200 * 4 байта (для указателей от каждого Vertex на два Vector3 элемента)
  • 200 * 8 байт (для 8-байтовых служебных данных, которые вы платите за создание Vector3 класса)
  • 200 * 12 байтов (для фактической полезной нагрузки 3 float на Vector3)

6000 байт (в 32-битной системе).

Как тип значения, это просто 200 * 12 байт = 2400 байт. Гораздо эффективнее в пространстве, не говоря уже о более низком уровне косвенности при чтении массива.

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

2 голосов
/ 19 апреля 2010

Недавно мы переключили некоторые математические типы (vec3, vec4, матрицы и т. Д.) На использование структур вместо классов, и, будучи немного быстрее в тестах, это также уменьшило давление GC (у нас были сотни мегабайт Vec3 распределения за относительно короткий промежуток времени, обнаруженные с помощью профилировщика CLR).

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

2 голосов
/ 19 апреля 2010

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

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

0 голосов
/ 19 апреля 2010

Структуры (обычно) хранятся в стеке, что может сделать их более эффективными, но, вероятно, недостаточно для заметного изменения.

http://www.c -sharpcorner.com / UploadFile / rmcochran / csharp_memory01122006130034PM / csharp_memory.aspx? ArticleID = 9adb0e3c-b3f6-40b5-98b5-413b6d348b91

0 голосов
/ 19 апреля 2010

Я полагаю, вы беспокоитесь о перф?

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

Если вы вообще ориентируетесь на .NET CE, вам, вероятно, следует рассмотреть возможность использования структур, поскольку GC не так эффективен, как полная реализация .NET.

...