无法使modf()在多线程中工作

时间:2015-10-24 07:55:44

标签: c++ multithreading openmp

我已经实现了两个不同的函数来将double数字舍入为整数。

这是第一个功能

static inline int round_v1(double value) 
{
    int t;
    __asm
    {
        fld value;
        fistp t;
    }
    return t;
}

这是第二个功能

static inline int round_v2(double value) 
{
    double intpart, fractpart;
    fractpart = modf(value, &intpart);
    if ((fabs(fractpart) != 0.5) || ((((int)intpart) % 2) != 0))
        return (int)(value + (value >= 0 ? 0.5 : -0.5));
    else
        return (int)intpart;
}

这两个函数在单线程中都可以正常工作,但第二个函数不能在多线程中工作(使用openMP)。当我使用第二个程序时,程序崩溃了。 以下是调用round_v1round_v2函数的主要代码。

void
BilateralFilter_Invoker::doFilter() const
{
    if (!src || !dst) return;
    int i, j;
    int src_width = width + (radius << 1);

    omp_set_num_threads(2);
    #pragma omp parallel for
    for (i = 0; i < height; ++i)
    {
        unsigned char* pSrc = src + (i+radius)*src_step + radius;
        unsigned char* pDst = dst + i*dst_step;
        for (j = 0; j < width; ++j)
        {
            float sum = 0.f, wsum = 0.f;
            int  val0 = pSrc[j];

            for (int k = 0; k < maxk; ++k)
            {
                int val = pSrc[j + space_offset[k]];
                float w = space_weight[k] * color_weight[std::abs(val-val0)];
                sum  += val * w;
                wsum += w;
            }

            //pDst[j] = (unsigned char)round_v2(sum / wsum);
            pDst[j] = (unsigned char)round_v1(sum / wsum);
        }
    }
}

变量srcdstheightwidthsrc_stepdst_stepradius,{{1 },maxkspace_offsetspace_weight是BilateralFilter_Invoker类的成员变量。

我只在调用color_weight时分别调用round_v1round_v2进行测试和程序崩溃。我想知道round_v2函数是否会导致这个问题。为了进一步测试,我评论这一行

modf(double, double*)

并将其替换为

fractpart = modf(value, &intpart);

我再次运行程序,它没有再次崩溃。我不知道fractpart = intpart = value; 是否会导致此问题。或者我的代码中可能存在错误导致问题而不是modf(double, double*)函数。

请注意,我使用的操作系统是Windows7,编译器是VC10。

1 个答案:

答案 0 :(得分:4)

你在SO上使用OpenMP犯了最常见的错误。你需要将内循环的迭代器设为私有。你可以做到

#pragma omp parallel for private(j)

或使用循环初始声明

for (int j = 0; j < width; ++j)

事实上,由于你从不在它们适用的循环之外使用ij,所以没有理由在循环之外声明它们C89样式。