В настоящее время я конвертирую программу, которая изначально предназначалась для OpenCL, в C ++, и у меня возникли некоторые проблемы с одной конкретной ее частью.
Одно из выражений, обычно используемых в указанной программе, включает в себя 32-разрядное значение с плавающей запятой, преобразование его в целое число (т.е. не округление его до целого числа, а интерпретацию тех же данных, что и int - think reinterpret_cast), выполнение некоторого бита закручивая магию на нем и затем преобразовывая его обратно в число с плавающей точкой (еще раз, не фактическое преобразование, а реинтерпретация тех же данных). Хотя это хорошо работает в OpenCL, с C ++ и gcc это нарушает строгие правила псевдонимов, нарушая программу, если оптимизация включена, и, в зависимости от архитектуры, может потребовать дорогостоящего хранения load-hit-store, поскольку регистры с плавающей запятой и целочисленные регистры разделены.
Мне удалось эффективно избежать большинства этих выражений, но есть одно, я не уверен, можно ли сделать это быстрее. По сути, цель состоит в том, чтобы очистить несколько бит справа от числа с плавающей запятой; код OpenCL делает это примерно так:
float ClearFloatBits(float Value, int NumberOfBits) {
return __int_as_float((__float_as_int(Value) >> NumberOfBits) << NumberOfBits);
}
Поскольку это по существу округление от указанной (двоичной) цифры, моя версия C ++ теперь выглядит так:
float ClearFloatBits(float Value, int NumberOfBits) {
float Factor = pow(2.0f, 23 - NumberOfBits);
return ((int)(Value*Factor))/Factor;
}
Там, где pow
и деление, конечно, заменены поиском LUT и соответствующим умножением, здесь опущено для лучшей читаемости.
Есть ли лучший способ сделать это? Что меня особенно беспокоит, так это (int) преобразование в округление вниз, которое, я думаю, является самой дорогой частью. Гарантируется, что число с плавающей точкой, передаваемое функции, представляет собой число от 1,0 (включительно) до 2,0 (исключая), если это помогает.
Заранее спасибо