Вопрос: Оптимизация кода на C++ | Добавлено: 13.03.11 21:02 |
Автор вопроса: ![]() |
Подскажите можно ли оптимизировать этот код -
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 Автор ответа: ![]() ![]() ![]() ![]() Вопросов: 87 Ответов: 2795 |
Web-сайт: Профиль | Цитата | #1 | Добавлено: 13.03.11 21:25 |
расставить отступы![]() |
Номер ответа: 2 Автор ответа: ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Вопросов: 20 Ответов: 79 |
Web-сайт: Профиль | Цитата | #2 | Добавлено: 13.03.11 21:49 |
в смысле раставить отступы? |
Номер ответа: 3 Автор ответа: ![]() ![]() ![]() ![]() Вопросов: 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 Автор ответа: ![]() ![]() ![]() ![]() Вопросов: 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 Автор ответа: ![]() ![]() ![]() ![]() Вопросов: 246 Ответов: 3333 |
Web-сайт: Профиль | Цитата | #7 | Добавлено: 13.03.11 23:48 |
PS: Раста-кошерный вариант так же предполагает, что если считаешь процессором, то по возможности кэшировать. Ибо для видеокарты это несущественно.
PPS: SSE4.2 в разных ситуациях может ускорить обработку до 10 раз. В частности, наложение картинки с альфа-канлом на SSE4 работает в 9 быстрее обычного наложения (бенчмарки сами ищите). Смекнули? |
Номер ответа: 8 Автор ответа: ![]() ![]() ![]() ![]() Вопросов: 246 Ответов: 3333 |
Web-сайт: Профиль | Цитата | #8 | Добавлено: 13.03.11 23:54 |
Еще можно найти отношение производительности CPU/GPU, разделить с таким соотношением картинку на две части и отправить на параллельную обработку и CPU, и GPU одновременно. При этом на процессоре использовать распараллеливание и всякие SSE и MMX, а на видеокарте по возможности самые мясные шейдеры (в смысле быстрые, необязательно новые). Вот тогда все ресурсы мясо, смекаешь? |
Номер ответа: 9 Автор ответа: ![]() ![]() ![]() ![]() Вопросов: 87 Ответов: 2795 |
Web-сайт: Профиль | Цитата | #9 | Добавлено: 14.03.11 01:07 |
А как же вариант - переписать на ассемблере?
И кстати - самое легкое, можно упростить формулу
Для R, G и B можно записать так
|
Номер ответа: 10 Автор ответа: ![]() ![]() ![]() ![]() Вопросов: 87 Ответов: 2795 |
Web-сайт: Профиль | Цитата | #10 | Добавлено: 14.03.11 01:11 |
Нет, не так. Лучше будет, вверху:
double xxx = -127.5 * Contrast + 127.5 а в циклах Pixel = xxx + Contrast * R{или G или B} |
Номер ответа: 11 Автор ответа: ![]() ![]() 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 Автор ответа: ![]() ![]() ![]() ![]() Вопросов: 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 поток идёт до половины указателя с начала,а другой тоже до половины,но с конца - и все это дело одновременно.Можно ли так сделать,если гарантировано,что потоки одновременно не захотят изменить одно и тоже значение????......или так совсем не правильно??? |
|