如果元素遵循许多约束,我想使用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));
答案 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但不会产生错误。我希望有一个干净的解决方案,但我想我仍然坚持使用目前的解决方案。