Использование Action‹PointerClass*› в качестве аргумента

Я создаю критически важное для производительности приложение, которое реализует манипулирование изображениями. Я использую некоторые указатели пикселей, используя свою структуру с именем Pixel для некоторой обработки. У меня есть много частей кода, которые перебирают все данные растрового изображения, и ради возможности повторного использования кода и модульности я разрабатываю метод, который будет выполнять действие и применять его ко всем пикселям изображения (например, карта функция). Однако, когда я пишу Action<Pixel*>, Visual Studio жалуется на код, в котором говорится, что тип Pixel* нельзя использовать в качестве аргумента типа. Весь класс находится в контексте unsafe, и я везде использую указатели Pixel, но я просто не могу использовать пиксельный указатель в качестве класса шаблона Action.

Я могу использовать Action<IntPtr>, но мне нужно будет преобразовать его в соответствующие указатели внутри тела метода на КАЖДОЙ итерации, что убьет всю идею «критичности к производительности».


person Can Poyrazoğlu    schedule 12.08.2011    source источник
comment
Мне нужна ссылка на экземпляр Pixel, который является struct   -  person Can Poyrazoğlu    schedule 13.08.2011
comment
Преобразование в/из IntPtr не приведет к сильному снижению производительности (преобразование в основном просто информирует компилятор о том, что вы явно хотите интерпретировать данные определенным образом). Однако вызов через указатель функции для каждого пикселя будет большим ударом по производительности. Я бы порекомендовал выполнить профилирование, чтобы определить, где на самом деле находятся ваши узкие места; указатели в .NET не обязательно быстрее [чем, скажем, доступ к массиву] (на самом деле они могут быть медленнее в некоторых случаях), и вы можете быть удивлены, какие вещи на самом деле замедляют вас.   -  person Dan Bryant    schedule 13.08.2011
comment
Я использую указатели Pixel, в отличие от методов GetPixel и SetPixel метода Bitmap, и это НАМНОГО быстрее (без делегатов). Но я использую почти один и тот же код снова и снова, где, помимо скучного копирования/вставки/изменения некоторых битов, он также очень подвержен опечаткам/логическим ошибкам. Что общего во ВСЕХ из них, так это то, что я блокирую растровое изображение и что-то делаю с каждым пикселем, перебирая пиксели с помощью указателей, а затем разблокирую изображение. Мне нужно несколько способов передать эту операцию, которую я применяю к каждому отдельному пикселю, и это заметно сделает меня более продуктивным.   -  person Can Poyrazoğlu    schedule 13.08.2011
comment
Я создаю критически важное для производительности приложение, реализующее манипуляции с изображениями. — и вы выбрали для этого C#... почему? Дело не в том, что вы не можете получить хорошую производительность от управляемого языка, но вам придется прыгать через кучу обручей, и в конце концов это просто не стоит того. Для того, что вы хотите сделать, C или C++ - лучший выбор.   -  person Ed S.    schedule 13.08.2011
comment
ну, это часть общей библиотеки, используемой как ASP.NET, так и клиентским программным обеспечением C#. при правильном использовании указателей разница в производительности между С++ и С# незначительна, а с точки зрения производительности С# превосходит С++.   -  person Can Poyrazoğlu    schedule 13.08.2011


Ответы (2)


Кажется, ничто не заставляет вас использовать Action<T>, поэтому вы можете создать свой собственный тип делегата. Я не нашел способ сделать это в общем виде, но это работает:

unsafe delegate void PixelAction(Pixel* ptr);

Имейте в виду, что если это действительно критично для производительности, вызов делегата будет медленнее, чем прямой вызов метода. Возможно, лучше использовать другой способ, например дублирование кода (если это сработает в вашем случае) или генерацию кода либо во время компиляции, либо во время выполнения с использованием Reflection.Emit или CodeDOM.

person svick    schedule 12.08.2011
comment
да. этот ответ заставил меня думать так же :) работа с Actions заставила меня полностью забыть об обычных делегатах, я попытаюсь реализовать это. - person Can Poyrazoğlu; 13.08.2011

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

Я думаю, что ваш единственный подход будет состоять в том, чтобы определить Action‹IntPtr› и приводить по мере необходимости с обеих сторон. Я не думаю, что снижение производительности будет таким сильным, как вы думаете, при компиляции с оптимизацией.

РЕДАКТИРОВАТЬ: оказывается, что ниже не работает (CS0208)

Либо так, либо вместо использования Action‹T› может работать определение собственного типа делегата:

delegate void PointerAction<T>(T* ptr);

person Timothy Fries    schedule 12.08.2011
comment
Похоже, это не работает: «Указатели и буферы фиксированного размера можно использовать только в небезопасном контексте». Если я добавлю unsafe, то: «Невозможно взять адрес, получить размер или объявить указатель на управляемый тип ('T')». - person svick; 13.08.2011