2014-04-18 4 views
4

난 부동 소수점 계산을 사용하는 이미지 처리 프로그램이 있습니다. 그러나, 나는 부동 소수점 지원이없는 프로세서에 이식해야합니다. 그래서 고정 소수점 계산을 사용하도록 프로그램을 변경해야합니다. 이를 위해서는 부동 소수점 계산의 중간 값을 포함하여 모든 값의 범위를 알아야 할 부동 소수점 숫자의 적절한 비율 조정이 필요합니다.부동 소수점 값의 범위 분석?

방금 ​​프로그램을 실행하고 자동으로 프로그램의 모든 부동 소수점 계산 범위를 제공하는 방법이 있습니까? 범위를 수동으로 파악하는 것은 너무 번거롭기 때문에 작업을 수행하는 데 필요한 도구가 있다면 정말 멋지게 될 것입니다!

+1

soft-float 구현을 사용할 수 없습니까? 나는 당신이 요구하는 그런 도구에 대해 모른다. –

답변

3

당신은이 라인을 따라, 당신의 부동 유형 (live example)를 일부 "측정"교체를 사용할 수 있습니다

template<typename T> 
class foo 
{ 
    T val; 

    using lim = std::numeric_limits<int>; 

    static int& min_val() { static int e = lim::max(); return e; } 
    static int& max_val() { static int e = lim::min(); return e; } 

    static void sync_min(T e) { if (e < min_val()) min_val() = int(e); } 
    static void sync_max(T e) { if (e > max_val()) max_val() = int(e); } 

    static void sync(T v) 
    { 
     v = std::abs(v); 
     T e = v == 0 ? T(1) : std::log10(v); 
     sync_min(std::floor(e)); sync_max(std::ceil(e)); 
    } 

public: 
    foo(T v = T()) : val(v) { sync(v); } 
    foo& operator=(T v) { val = v; sync(v); return *this; } 

    template<typename U> foo(U v) : foo(T(v)) {} 
    template<typename U> foo& operator=(U v) { return *this = T(v); } 

    operator T&() { return val; } 
    operator const T&() const { return val; } 

    static int min() { return min_val(); } 
    static int max() { return max_val(); } 
}; 

이 의미

int main() 
{ 
    using F = foo<float>; 
    F x; 

    for (F e = -10.2; e <= 30.4; e += .2) 
     x = std::pow(10, e); 

    std::cout << F::min() << " " << F::max() << std::endl; // -11 31 
} 

처럼 사용할 수 있도록 당신이 별명을 정의해야 부동 유형 (float 또는 double)에 대해 (예 : Float) 사용하고 프로그램 전체에서 일관되게 사용하십시오. 이것은 불편할 수 있지만 결국 유익한 것으로 판명 될 수 있습니다 (프로그램이 더 일반적이기 때문에). 당신의 코드가 이미 플로팅 타입으로 템플릿 화되어 있다면 더 좋을 것입니다.

이 매개 변수화 한 후, 당신은 할 Float를 정의하여 "측정"또는 "릴리스"모드를 프로그램을 전환 할 수 있습니다 Tfloat 또는 double입니다 foo<T> 또는 T.

좋은 점은 외부 도구가 필요 없다는 것입니다. 사용자 자신의 코드가 측정을 수행합니다. 나쁜 점은 현재 설계된대로 모든 중간 결과를 포착하지 못한다는 것입니다. 이 경우 foo에 모든 연산자 (예 : 산술 연산자)를 정의해야합니다. 이 작업을 수행 할 수 있지만 더 많은 작업이 필요합니다.

+0

정말 대단합니다. 그것은 멋진 기능의 이러한 종류로 인해, 나는 C++을 사랑합니다 :)! – MetallicPriest

2

자체에 포함 된 C 프로그램의 경우, 아래 예를 h를 들어, 부동 소수점 변수의 범위를 얻기 위해 Frama-C's value analysis를 사용할 수 있습니다

value analysis on floating-point variable h

그리고 변수 gh에서 계산 :

value analysis on floating-point variable g

입력 범위를 설명하는 사양 언어가 있습니다 (informat 이온 없이는 아무 것도 유익하지 못합니다).

/*@ ensures \is_finite(\result) && l <= \result <= u ; */ 
float float_interval(float l, float u); 

FRAMA-C는 최근 데비안과 우분투 바이너리 패키지로, 리눅스에 설치하는 것이 가장 쉬운 방법이다 (그러나 보통이 아닌 : 위의 예에서, 내가 할 것으로 예상 무슨 기능 float_interval 지정하려면 해당 언어를 사용 최신) 버전을 배포판에서 사용할 수 있습니다.

코드를 게시 할 수 있다면이 방법이 현실적인 지 여부를 알 수 있습니다. 코드가 C++ 인 경우 (예를 들어 질문에 여러 언어 태그가 태그되어 있음), Frama-C의 현재 버전은 C 프로그램 만 허용하므로 도움이되지 않습니다.

+0

좋습니다. 내가 이해 한 것은 도구가 정적 분석/추상 해석을 통해 프로그램을 실행하지 않고 범위를 계산할 수 있다는 것입니다. 개별 변수의 예를 보여 주었지만 범위 내에서 프로그램의 모든 부동 소수점 변수를 집합 적으로 고려할 수도 있습니다. 둘째, 변수의 입력 범위를 지정할 수도 있습니까? 입력은 변수가 초기화되는 값을 의미합니다. – MetallicPriest

+1

@ MetallicPriest 필자는 답안의 예제를 변경하여 두 번째 질문을 처리 할 수있는 방법을 설명했으며, 이제는 분석기가 '\ is_finite (\ result) && l <= \'설명 만 알고있는 함수 'float_interval' 결과 <= u'. –

+0

@ MetallicPriest 첫 번째 질문에 대해,이 접근법의 장점 중 하나는 iavr의 제안과 비교할 때 각 계산의 범위를 관찰하고 각각에 대해 최적의 표현을 사용할 수 있다는 것입니다. 예를 들어, 프로그램이 [1.0 .. 256.0] 범위의 두 숫자를 곱하면 8Q8 * 8Q8 -> 16Q0 곱셈이 가장 좋다고 추측 할 수 있습니다. 현재 설명되어있는 iavr의 제안은 일부 숫자가 65025까지 올라간다는 것을 알려줄뿐입니다. –

3

부동 소수점을 지원하지 않는 하드웨어에서 부동 소수점 코드를 사용할 수 없다는 것은 사실이 아닙니다. 컴파일러는 부동 소수점 연산을 수행하는 소프트웨어 루틴을 제공합니다. 단지 느릴 수 있지만, 귀하의 신청서, 즉 최소한의 저항의 길입니다.

고정 소수점 데이터 형식 클래스를 구현하고 해당 멤버 함수가 오버/언더 플로우를 디버그 옵션으로 검색하는 것이 가장 간단합니다 (그렇지 않으면 검사로 인해 코드가 느려질 것이므로).

나는 당신이 Anthony Williams' fixed-Point math C++ library을 보길 권합니다. 그것은 C++로 광범위한 함수와 연산자 오버로딩을 사용하는 fixed 클래스를 정의하므로 기존 코드의 float 또는 doublefixed으로 바꾸는 것만으로 간단하게 사용할 수 있습니다. 기본 정수 데이터 형식으로 int64_t을 사용하며 34 정수 비트와 28 소수 비트 (34Q28)를 사용하므로 약 8 자리 소수점 및 int32_t보다 넓은 범위에 적합합니다.

내가 제안한 언더/오버 플로우 검사가 없지만 자신을 추가하는 것이 좋은 출발점입니다.

32 비트 ARM에서이 라이브러리는 소프트웨어 부동 소수점보다 약 5 배 빠르게 수행되며 C 코드의 ARM VFP 장치와 성능면에서 비교할 수 있습니다.

이 라이브러리의 sqrt() 함수는 보존 할 수있는 중간 계산에서 하위 비트를 잃어 버리기 때문에 매우 작은 값에 대해서는 정밀도가 떨어집니다. this question에서 제시 한 코드로 바꾸면 개선 될 수 있습니다.

+0

예 부동 소수점 에뮬레이션을위한 코드를 생성하는 컴파일러의 기능을 알고 있지만 너무 느리다는 것입니다. 그래서 나는 고정 지점을 선호한다. – MetallicPriest

+1

@ MetallicPriest : 충분히 공정하지만, 귀하의 질문에 명확하지 않다, – Clifford