Страница: 1 | 2 |
Вопрос: Оптимизация кода на C++
Добавлено: 13.03.11 21:02
Автор вопроса: Лёха | Web-сайт:
Подскажите можно ли оптимизировать этот код -
void ProcessFilter_Contrast(IMG * Pic, int Value)
{
if(IsInInterval(Value, -100, 100))
{
unsigned char R, G, B;
UINT IDX;
double Pixel;
double Contrast;
Contrast = (100.0 + (double)Value) / 100.0;
Contrast = Sqr((float)Contrast);
for(int Y = 0; Y < Pic -> Height; Y++)
{
for(int X = 0; X < Pic -> Width; X++)
{
IDX = (Y * Pic -> Width + X) * Pic -> BytesPerPixel;
R = *(Pic -> Data + IDX + Pic -> R_IDX);
G = *(Pic -> Data + IDX + Pic -> G_IDX);
B = *(Pic -> Data + IDX + Pic -> B_IDX);
Pixel = R / 255.0;
Pixel = Pixel - 0.5;
Pixel = Pixel * Contrast;
Pixel = Pixel + 0.5;
Pixel = Pixel * 255.0;
*(Pic -> Data + IDX + Pic -> R_IDX) = (unsigned char)Clamp(Pixel, 0.0, 255.0);
Pixel = G / 255.0;
Pixel = Pixel - 0.5;
Pixel = Pixel * Contrast;
Pixel = Pixel + 0.5;
Pixel = Pixel * 255.0;
*(Pic -> Data + IDX + Pic -> G_IDX) = (unsigned char)Clamp(Pixel, 0.0, 255.0);
Pixel = B / 255.0;
Pixel = Pixel - 0.5;
Pixel = Pixel * Contrast;
Pixel = Pixel + 0.5;
Pixel = Pixel * 255.0;
*(Pic -> Data + IDX + Pic -> B_IDX) = (unsigned char)Clamp(Pixel, 0.0, 255.0);
}
}
}
else
{
MessageBoxA(0, "Invalid Contrast Value!", "Error!", MB_OK | MB_ICONERROR);
}
}
Заранее спасибо
Ответы
Всего ответов: 21
Номер ответа: 1
Автор ответа:
Winand
Вопросов: 87
Ответов: 2795
Web-сайт:
Профиль | | #1
Добавлено: 13.03.11 21:25
расставить отступы Вообще не знаю, и вопрос размытый
Номер ответа: 2
Автор ответа:
Лёха
Вопросов: 20
Ответов: 79
Web-сайт:
Профиль | | #2
Добавлено: 13.03.11 21:49
в смысле раставить отступы?
Номер ответа: 3
Автор ответа:
Winand
Вопросов: 87
Ответов: 2795
Web-сайт:
Профиль | | #3
Добавлено: 13.03.11 22:12
http://ru.wikipedia.org/wiki/Отступ_(программирование) ящитаю 1TBS самый труъ
Номер ответа: 4
Автор ответа:
Лёха
Вопросов: 20
Ответов: 79
Web-сайт:
Профиль | | #4
Добавлено: 13.03.11 22:21
ты про форматирование кода?....оно убралось при добавлении тэга [code]
Номер ответа: 5
Автор ответа:
Лёха
Вопросов: 20
Ответов: 79
Web-сайт:
Профиль | | #5
Добавлено: 13.03.11 22:28
Что никак нельзя?
Номер ответа: 6
Автор ответа:
VβÐUηìt
Вопросов: 246
Ответов: 3333
Web-сайт:
Профиль | | #6
Добавлено: 13.03.11 23:45
Бональный вариант: распараллелить.
Кошерный вариант: кэшировать уже просчитанные цвет
Еще более кошерный вариант: перевести все на целочисленные расчеты
Совсем кошерный вариант: запилить васю на SSE4.2/SSE4/SSE3/SSE2/SSE/MMX (если уж совсем доисторический процессор). А вообще, SSE4.2 по-моему есть во всех компах где Windows 7.
Труъ-раста вариант: запилить васю на GPU. Тупо через WPF.
Раста-кошерный вариант: если есть возможность, использовать видеокарту. Нет - использовать процессорные SSE4.2. Нет SSE4.2 - просто SSE4. Ну и так далее вплоть до MMX. Если нет MMX - делаем простые обсчеты на C++. Причем при обсчете на процессоре, если есть больше одного ядра, распараллеливать это дело. В итоге твой василий будет работать максимально быстро, как это может делать комп.
Номер ответа: 7
Автор ответа:
VβÐUηìt
Вопросов: 246
Ответов: 3333
Web-сайт:
Профиль | | #7
Добавлено: 13.03.11 23:48
PS: Раста-кошерный вариант так же предполагает, что если считаешь процессором, то по возможности кэшировать. Ибо для видеокарты это несущественно.
PPS: SSE4.2 в разных ситуациях может ускорить обработку до 10 раз. В частности, наложение картинки с альфа-канлом на SSE4 работает в 9 быстрее обычного наложения (бенчмарки сами ищите). Смекнули?
Номер ответа: 8
Автор ответа:
VβÐUηìt
Вопросов: 246
Ответов: 3333
Web-сайт:
Профиль | | #8
Добавлено: 13.03.11 23:54
Еще можно найти отношение производительности CPU/GPU, разделить с таким соотношением картинку на две части и отправить на параллельную обработку и CPU, и GPU одновременно. При этом на процессоре использовать распараллеливание и всякие SSE и MMX, а на видеокарте по возможности самые мясные шейдеры (в смысле быстрые, необязательно новые). Вот тогда все ресурсы мясо, смекаешь?
Номер ответа: 9
Автор ответа:
Winand
Вопросов: 87
Ответов: 2795
Web-сайт:
Профиль | | #9
Добавлено: 14.03.11 01:07
А как же вариант - переписать на ассемблере?
И кстати - самое легкое, можно упростить формулу
Для R, G и B можно записать так
Номер ответа: 10
Автор ответа:
Winand
Вопросов: 87
Ответов: 2795
Web-сайт:
Профиль | | #10
Добавлено: 14.03.11 01:11
Нет, не так. Лучше будет, вверху:
double xxx = -127.5 * Contrast + 127.5
а в циклах
Pixel = xxx + Contrast * R{или G или B}
Номер ответа: 11
Автор ответа:
AWP
ICQ: 345685652
Вопросов: 96
Ответов: 1212
Web-сайт:
Профиль | | #11
Добавлено: 14.03.11 13:43
А т.к. R от 0-255 Можно заранее просчитать все варианты Contrast * R, занести в массив и брать оттуда - быстрее чем умножение будет.
Номер ответа: 12
Автор ответа:
Лёха
Вопросов: 20
Ответов: 79
Web-сайт:
Профиль | | #12
Добавлено: 14.03.11 19:53
А про распараллеливание можно по подробней?
Номер ответа: 13
Автор ответа:
VβÐUηìt
Вопросов: 246
Ответов: 3333
Web-сайт:
Профиль | | #13
Добавлено: 14.03.11 20:01
Гугли многопоточность, потоки и т.п. Если в краце неточно, не совсем верно, но понятно, поток - это отдельная функция, которая выполняется параллельно с другими. То есть ты создал две функции (обычных, а-ля Sub Rasta и Sub Vasya), и запустил их не последовательно, а параллельно. Потоки любят распределяться по ядрам процессора и выполняться параллельно, однако операционная система умеет выполнять два и более потока на одном ядре (разумеется с падениемпроизводительности). В итоге выйгрыш получается при количестве потоков, равном количеству ядер - потоки по ядрам сами смекнут и раскидаются. Таким образом, прирост будет только в случае дву/трех/четырех/шести/восьми/двенадцати/ну ты понел-ядерных процессоров. Если процессор одноядерный - прироста не будет (про HyperThreading потом). Так вот. Это так, теория. Потоки в C++, имхо, УГ. Поэтому ты, конечно, можешь юзать API CreateThread и т.п. но лучше либо юзать C++ CLI, где это вкусно обернуто, либо C#, а из под него вызывать функцию по обработке в нескольких потоках. Еще тебе придется погуглить синхронизацию потоков, смекнуть, и запилить ее. Смекаешь?
Номер ответа: 14
Автор ответа:
Лёха
Вопросов: 20
Ответов: 79
Web-сайт:
Профиль | | #14
Добавлено: 14.03.11 20:48
Спасибо,буду пробовать!Эта функция и так довольно быстро выполняется,но хочется,чтоб ещё быстрей!
Номер ответа: 15
Автор ответа:
Лёха
Вопросов: 20
Ответов: 79
Web-сайт:
Профиль | | #15
Добавлено: 14.03.11 20:55
Тут такая мыслишка в голову пришла : если в одном потоке данные начинают обрабатываться с начала указателя(Допустим unsigned char * Data),а в другом с конца этого указателя.1 поток идёт до половины указателя с начала,а другой тоже до половины,но с конца - и все это дело одновременно.Можно ли так сделать,если гарантировано,что потоки одновременно не захотят изменить одно и тоже значение????......или так совсем не правильно???