Parallel processing 中大;并行搜索

Parallel processing 中大;并行搜索,parallel-processing,cuda,Parallel Processing,Cuda,我想做以下几件事: 假设我有一个大小为N(N相当大)的排序数字向量和一个数字x。 我想并行搜索这个向量中x的正确位置。例如: myVector=[1,2,3,…,10000]和x=3.2 那我就得回去了。找到正确位置的第一个线程应该中断其他线程的工作。然后花费的时间将最小化:t=min(t_1,t_2,…,t_线程数) 您认为使用多线程寻找正确位置会更快吗? 线程之间的通信如何?因为一旦某个值被某个线程变红并且与搜索不匹配,其他线程就必须在搜索过程中跳过该值(可能是必须更改的布尔值) 关于此算法

我想做以下几件事: 假设我有一个大小为N(N相当大)的排序数字向量和一个数字x。 我想并行搜索这个向量中x的正确位置。例如:

myVector=[1,2,3,…,10000]和x=3.2

那我就得回去了。找到正确位置的第一个线程应该中断其他线程的工作。然后花费的时间将最小化:t=min(t_1,t_2,…,t_线程数) 您认为使用多线程寻找正确位置会更快吗? 线程之间的通信如何?因为一旦某个值被某个线程变红并且与搜索不匹配,其他线程就必须在搜索过程中跳过该值(可能是必须更改的布尔值)


关于此算法,您有什么建议可以分享吗?

不需要在线程和块之间通信。您可以检查当前索引的值是否大于预期值。如果大于预期值,则返回。大多数线程将无法通过此检查

现在只有索引值小于预期值的线程。请检查下一个值是否大于或等于查询,并返回相应的索引

这是我在早上5点写的未经测试的内核

template<typename ty>
__global___ static void search(int *out, ty *list, ty val, int n)
{
    int start = threadIdx.x + blockIdx.x * blockDim.x;
    for (int idx = start; idx < n; idx += gridDim.x * blockDim.x) {
        if (list[idx] >= val) return;
        ty next = list[idx + 1];
        if (idx == n-1 || next >= val) {
            *out = next == val ? (idx + 1) : idx;
            return;
        }
     }
}
模板
__全局\静态无效搜索(int*out,ty*list,ty val,int n)
{
int start=threadIdx.x+blockIdx.x*blockDim.x;
对于(int idx=start;idx=val)返回;
ty next=列表[idx+1];
if(idx==n-1 | | next>=val){
*out=next==val?(idx+1):idx;
回来
}
}
}

也就是说,您真的不想这样做。您可以得到最坏情况下的性能O(logn)在使用CPU时。这意味着搜索十亿个元素可以在32个步骤中完成。除非gpu上已经有数据并且希望避免内存复制,否则在CPU上进行搜索会更好。

不久前,我编写了以下代码,执行类似的操作:

#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <stdio.h>
#include <stdlib.h>

__global__ void fast_finder(unsigned int *g_found, float x, float *y)
{
    unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;
    unsigned int pos = (unsigned int)(x == y[i]);
    g_found[i * (1 - pos)] = i * pos;
}

int main(int argc, char *argv[])
{
    int N = 65536;
    unsigned int h_found, *d_found;
    float *h_y = (float *)malloc(N * sizeof(float)), *d_y, x = 5.0f;
    int nThreads = 1024, nBloks = N / nThreads;

    for (int i = 0; i < N; ++i) h_y[i] = (float)(N - i - 1);

    if (x != h_y[0]) {
        cudaSetDevice(0);
        cudaMalloc((void **)&d_found, N * sizeof(unsigned int));
        cudaMalloc((void **)&d_y, N * sizeof(float));
        cudaMemcpy(d_y, h_y, N * sizeof(float), cudaMemcpyHostToDevice);

        fast_finder<<<nBloks, nThreads>>>(d_found, x, d_y);
        cudaThreadSynchronize();

        cudaMemcpy(&h_found, d_found, sizeof(unsigned int), cudaMemcpyDeviceToHost);
        if (h_found) printf("%g found on %d. position!\n", x, h_found);
        else printf("%g not found!\n", x);

        cudaFree(d_y);
        cudaFree(d_found);

    } else printf("%g found on the first position!\n", x);

    free(h_y);

    getchar();
    return EXIT_SUCCESS;
}
在这种情况下,
y
不需要排序,但必须只包含唯一的值。可以很容易地将此代码更改为一个查找(设备部件)索引,其中插入提供的
x
,如下所示:

g_found = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
__global__ void fast_finder(unsigned int *g_found, float x, float *y)
{
    unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;
    unsigned int pos = (unsigned int)(x >= y[i] || x <= y[i+1]);
    g_found[i * (1 - pos)] = (i + 1) * pos;
}
\uuuuu全局\uuuuuu无效快速查找器(未签名整数*g\u已找到,浮点x,浮点*y)
{
无符号整数i=blockIdx.x*blockDim.x+threadIdx.x;

unsigned int pos=(unsigned int)(x>=y[i]| | x,除非已排序的向量已经在设备内存中,否则使用CUDA对此没有意义。CPU上的二进制搜索具有复杂度log2 n。您可能感兴趣,或者如果您不熟悉推力,则有一个。