Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何同时写入和读取具有唯一递增值的CUDA数组?_Cuda - Fatal编程技术网

如何同时写入和读取具有唯一递增值的CUDA数组?

如何同时写入和读取具有唯一递增值的CUDA数组?,cuda,Cuda,我有一个共享内存数组,初始化如下 #define UNDEFINED 0xffffffff #define DEFINED 0xfffffffe __shared__ unsigned int array[100]; __shared__ count; // We have enough threads: blockDim.x > 100 array[threadIdx.x] = UNDEFINED; // Initialize count if (threadIdx.x ==

我有一个共享内存数组,初始化如下

#define UNDEFINED 0xffffffff
#define DEFINED   0xfffffffe

__shared__ unsigned int array[100];
__shared__ count;

// We have enough threads: blockDim.x > 100
array[threadIdx.x] = UNDEFINED;


// Initialize count
if (threadIdx.x == 0)
  count = 0;
线程可以随机访问
数组
。当线程访问
数组
时,如果它是
未定义的
,它必须向该元素写入一个唯一的值
count
,然后读取该值。如果数组元素已定义或已具有唯一值,则必须仅读取唯一值。棘手的部分是
array
count
都必须只更新一个线程。原子函数只更新1个变量,而不是2个变量。这里是我最后想到的方法,一个线程更新两个变量,同时阻塞其他线程,直到完成为止

value = atomicCAS(&array[randomIndex], UNDEFINED, DEFINED);
if (value == UNDEFINED) {
    value = atomicAdd(&count, 1);
    array[randomIndex] = value;
} 

// For case that value == DEFINED_SOURCe, wait for memory
// writes, then store value
__threadfence_block();
value = array[randomSource];

这里有一些棘手的并发问题。我不确定这是否适用于所有情况。有更好的建议或意见吗?

要获得递增值数组,请使用基于二叉树线程的prefx sum(也称为扫描算法)。优先于本地块(名称中的共享内存)?然后全局覆盖块,然后将每个总和添加回每个块。 此外,每个块读取的不是一个而是一些值可能是有效的,这些值等于物理上的“扭曲大小”,例如16个int值(我很抱歉,因为我很久以前就做过这件事,不知道CUDA中这件事的正确大小和正确名称)。
啊,顺便说一句,如果增量相等,最终值可以作为函数从local或global thread.id中检索,因此您根本不需要扫描。对于增量值数组,请使用prefx sum,也称为扫描算法,基于二叉树线程。优先于本地块(名称中的共享内存)?然后全局覆盖块,然后将每个总和添加回每个块。 此外,每个块读取的不是一个而是一些值可能是有效的,这些值等于物理上的“扭曲大小”,例如16个int值(我很抱歉,因为我很久以前就做过这件事,不知道CUDA中这件事的正确大小和正确名称)。
啊,顺便说一句,如果是等额递增,最终值可以作为函数从local或global thread.id中检索,因此您根本不需要扫描。

根据您的描述,写入
数组
元素的唯一时间是如果它包含值
未定义
。我们可以利用这一点

  • 线程将首先对所需的
    数组
    元素执行
    atomicCAS
    atomicCAS
    将配置为检查
    未定义的值。如果存在,它将替换为定义的
    。如果它不存在,它将不会替换它

  • 根据来自
    atomicCAS
    的返回结果,线程将知道数组元素是否包含
    UNDEFINED
    。如果执行了,则来自
    atomicCAS
    的返回结果将是
    未定义的
    ,然后线程将从
    计数
    中检索所需的唯一值,并使用该值将
    已定义的
    值修改为所需的唯一值

  • 我们可以在一行代码中完成此操作:

    // assume idx contains the desired offset into array
    if (atomicCAS(array+idx, UNDEFINED, DEFINED) == UNDEFINED) array[idx]=atomicAdd(&count, 1);
    
    更完整的代码可能如下所示:

    value = DEFINED;
    while (value == DEFINED){
      value = atomicCAS(&array[randomIndex], UNDEFINED, DEFINED);
      if (value == UNDEFINED) {
        value = atomicAdd(&count, 1);
        array[randomIndex] = value;}
      }
    
     // value now contains the unique value, 
     // either that was already present in array[randomIndex] 
     // or the value that was just written there
    

    根据您的描述,写入
    数组
    元素的唯一时间是它包含值
    未定义
    。我们可以利用这一点

  • 线程将首先对所需的
    数组
    元素执行
    atomicCAS
    atomicCAS
    将配置为检查
    未定义的值。如果存在,它将替换为定义的
    。如果它不存在,它将不会替换它

  • 根据来自
    atomicCAS
    的返回结果,线程将知道数组元素是否包含
    UNDEFINED
    。如果执行了,则来自
    atomicCAS
    的返回结果将是
    未定义的
    ,然后线程将从
    计数
    中检索所需的唯一值,并使用该值将
    已定义的
    值修改为所需的唯一值

  • 我们可以在一行代码中完成此操作:

    // assume idx contains the desired offset into array
    if (atomicCAS(array+idx, UNDEFINED, DEFINED) == UNDEFINED) array[idx]=atomicAdd(&count, 1);
    
    更完整的代码可能如下所示:

    value = DEFINED;
    while (value == DEFINED){
      value = atomicCAS(&array[randomIndex], UNDEFINED, DEFINED);
      if (value == UNDEFINED) {
        value = atomicAdd(&count, 1);
        array[randomIndex] = value;}
      }
    
     // value now contains the unique value, 
     // either that was already present in array[randomIndex] 
     // or the value that was just written there
    

    我不想保持一个连续的总数。我只是尝试将唯一的递增值写入随机和并发访问的数组。若那个唯一的值已经写入到那个元素中,那个么就直接读出它。若块中的所有线程都会做不同的事情,那个么这将比普通处理器慢得多,尤其是现代的4核处理器,不管怎样。不过,如果你愿意的话,看看CUDA原子操作的完整列表,我会看看关于XOR的东西,随便什么。我记得CUDA中有一种阻止线程的semafores。我不想保持一个运行的总和。我只是尝试将唯一的递增值写入随机和并发访问的数组。若那个唯一的值已经写入到那个元素中,那个么就直接读出它。若块中的所有线程都会做不同的事情,那个么这将比普通处理器慢得多,尤其是现代的4核处理器,不管怎样。但是如果你愿意的话,看看CUDA原子操作的完整列表,我会看看关于XOR的东西,不管什么。我记得CUDA中有一种阻止线程的semafores。正在接近解决方案。但可能仍然存在一个问题。如果两个线程同时使用相同的idx值访问该语句,那么在atomicCAS操作之后,第一个线程将array+idx设置为DEFINED,在该阻塞操作之后,第二个线程将查找array+idx==DEFINED。第二个线程不能保证获得计数值。在CUDA中,我们可以将其编写为一条语句,但编译器会将其分解为多条指令;值=数组[idx];之后仍然需要语句。如果线程读取
    D的值