Лучший пример динамического связывания - когда библиотека зависит от используемого оборудования. В древние времена математическая библиотека C считалась динамичной, поэтому каждая платформа могла использовать все возможности процессора для ее оптимизации.
Еще лучшим примером может быть OpenGL. OpenGl - это API, который по-разному реализован AMD и NVidia. И вы не можете использовать реализацию NVidia на карте AMD, потому что аппаратное обеспечение отличается. Из-за этого вы не можете статически связать OpenGL с вашей программой. Динамическое связывание используется здесь, чтобы позволить API быть оптимизированным для всех платформ.
Whether you choose to use a lookup table or not, your code is doing a lot of work each loop iteration that it really does not need to - likely enough to overshadow the cost of the convert and multiply.
Declare your pointers restrict, and pointers you only read from const. Multiply by 1/255th instead of dividing by 255. Don't calculate the pointers in each iteration of the inner loop, just calculate initial values and increment them. Unroll the inner loop a few times. Use vector SIMD operations if your target supports it. Don't increment and compare with maximum, decrement and compare with zero instead.
Something like
float* restrict floatpixel = floatbuffer;
BYTE const* restrict bytepixel = bytebuffer;
for( int size = width*height; size > 0; --size )
{
floatpixel[0] = bytepixel[0]*(1.f/255.f);
floatpixel[1] = bytepixel[1]*(1.f/255.f);
floatpixel[2] = bytepixel[2]*(1.f/255.f);
floatpixel[3] = 1.0f; // A
floatpixel += 4;
bytepixel += 4;
}
would be a start.
Не вычисляйте каждый раз 1/255. Не знаю, хватит ли у компилятора умен, чтобы это удалить. Рассчитайте его один раз и применяйте каждый раз повторно. Еще лучше, определите его как константу.
Да, таблица поиска определенно быстрее, чем выполнение большого количества делений в цикле. Просто создайте таблицу из 256 предварительно вычисленных значений с плавающей запятой и используйте значение байта для индексации этой таблицы.
Вы также можете немного оптимизировать цикл, удалив вычисление индекса и просто сделав что-то вроде
float *floatpixel = floatbuffer;
BYTE *bytepixel = bytebuffer;
for (...) {
*floatpixel++ = float_table[*bytepixel++];
*floatpixel++ = float_table[*bytepixel++];
*floatpixel++ = float_table[*bytepixel++];
*floatpixel++ = 1.0f;
}
Используйте для этого статическую таблицу поиска. Когда я работал в компании, занимающейся компьютерной графикой, у нас появилась жестко закодированная таблица поиска для этого, которую мы связали с проектом.
Вам нужно выяснить, в чем заключается узкое место:
Другой совет:
struct Scale {
BYTE operator()( const float f ) const { return f * 1./255; }
};
std::transform( float_table, float_table + itssize, floatpixel, Scale() );
Поисковая таблица - это самый быстрый способ преобразования :) Вот, пожалуйста:
Код Python для создания файла byte_to_float.h, который должен включать:
#!/usr/bin/env python
def main():
print "static const float byte_to_float[] = {"
for ii in range(0, 255):
print "%sf," % (ii/255.0)
print "1.0f };"
return 0
if __name__ == "__main__":
main()
И код C ++ для преобразования:
floatpixel[0] = byte_to_float[ bytepixel[0] ];
Simple isn не так ли?