推动 - 访问邻居

时间:2012-10-04 12:23:39

标签: thrust

如果元素遵循许多约束,我想使用Thrust的流压缩功能(copy_if)来从向量中提取元素的索引。这些约束之一取决于相邻元素的值(2D中为8,3D中为26)。我的问题是:如何在Thrust中获得元素的邻居?

'copy_if'的仿函数的函数调用操作符基本上如下:

__host__ __device__ bool operator()(float x) {
    bool mark = x < 0.0f;
    if (mark) {
        if (left neighbor of x > 1.0f) return false;
        if (right neighbor of x > 1.0f) return false;
        if (top neighbor of x > 1.0f) return false;
        //etc.
    }
    return mark;
}

目前我通过首先启动CUDA内核(在其中很容易访问邻居)来使用解决方法来适当地标记元素。之后,我将标记的元素传递给Thrust的copy_if,以提取标记元素的索引。


我遇到了counting_iterator,它直接使用threadIdx和blockIdx来获取已处理元素的索引。我尝试了下面的解决方案,但在编译时,它给了我一个“/usr/include/cuda/thrust/detail/device/cuda/copy_if.inl(151):错误:不支持未对齐的内存访问”。据我所知,我不是试图以不对齐的方式访问内存。有谁知道发生了什么和/或如何解决这个问题?

struct IsEmpty2 {
    float* xi;

    IsEmpty2(float* pXi) { xi = pXi; }

    __host__ __device__ bool operator()(thrust::tuple<float, int> t) {
        bool mark = thrust::get<0>(t) < -0.01f;
        if (mark) {
            int countindex = thrust::get<1>(t);
            if (xi[countindex] > 1.01f) return false;
            //etc.
        }
        return mark;
    }
};


thrust::copy_if(indices.begin(),
                indices.end(),
                thrust::make_zip_iterator(thrust::make_tuple(xi, thrust::counting_iterator<int>())),
                indicesEmptied.begin(),
                IsEmpty2(rawXi));

1 个答案:

答案 0 :(得分:1)

@phoad:你对共享内存你是对的,在我发布回复之后它让我感到震惊,后来认为缓存可能会帮助我。但是你的快速回应打败了我。然而,if语句在所有情况下执行的次数不到5%,因此使用共享内存或依赖缓存可能对性能的影响可以忽略不计。

元组只支持10个值,这意味着我需要3D元素中26个值的元组元组。使用元组和zip_iterator已经非常繁琐了,所以我将通过这个选项(也从代码可读性的角度来看)。我在设备函数中直接使用threadIdx.x等尝试了你的建议,但Thrust不喜欢这样。我似乎得到了一些无法解释的结果,有时我最终会出现Thrust错误。例如,以下程序生成'thrust :: system :: system_error'并带有'未指定的启动失败',尽管它首先正确地将“Processing 10”打印到“Processing 41”:

struct printf_functor {
    __host__ __device__ void operator()(int e) {
        printf("Processing %d\n", threadIdx.x);
    }
};

int main() {
    thrust::device_vector<int> dVec(32);
    for (int i = 0; i < 32; ++i)
        dVec[i] = i + 10;

    thrust::for_each(dVec.begin(), dVec.end(), printf_functor());

    return 0;
}

同样适用于print blockIdx.x Printing blockDim.x但不会产生错误。我希望有一个干净的解决方案,但我想我仍然坚持使用目前的解决方案。