首页 \ 问答 \ 无法将具有相同优先级的对象插入ConcurrentSkipListSet(Unable to insert objects of equal priority into ConcurrentSkipListSet)

无法将具有相同优先级的对象插入ConcurrentSkipListSet(Unable to insert objects of equal priority into ConcurrentSkipListSet)

我在使用ConcurrentSkipListSet处理观察者模式的简单线程安全实现时遇到问题,以便在插入期间跟踪观察者优先级。 大多数观察者都没有任何特殊的优先权归属于他们,并且遵循此Comparable#compareTo方法在比较时将显示相同的优先级(其中优先级是五个优先级的枚举值,范围从最高到最低):

public int compareTo(BaseLink<?> link) {
    return this.priority.compareTo(link.getPriority());
}

当我向ConcurrentSkipListSet添加具有相同优先级的观察者时,似乎在插入过程中会丢失一些添加的对象。 更改我在测试时创建的任何观察者的优先级会导致这些观察者被添加到集合中而没有问题,但我认为如果给予相同优先级的足够观察者,则问题将再次出现。

我不确定导致这个问题的原因,以及我应该做些什么来帮助解决这个问题。 我有什么办法可以解决这个问题吗? 或者,如果这是ConcurrentSkipListSet的固有问题,是否还有其他线程安全的数据结构可以为独特对象提供合理的高效插入和排序时间?


I am having an issue with a simplistic thread-safe implementation of the observer pattern using a ConcurrentSkipListSet to handle keeping track of observer priorities during insertion. The majority of observers will not have any special priority attributed to them, and following this Comparable#compareTo method will show as equal priority when compared (where priority is a value in an enum of five priorities ranging from highest to lowest):

public int compareTo(BaseLink<?> link) {
    return this.priority.compareTo(link.getPriority());
}

When I add observers of equal priorities to the ConcurrentSkipListSet , it seems like some of the added objects are simply lost during the insertion process. Changing the priorities of any of the observers I have created while testing this results in those observers being added to the set without issue, though I assume that given enough observers of the same priority the issue will arise again.

I am unsure about what is causing this issue, and of what I should do to help resolve it. Is there anything I can do to resolve this issue? Alternatively if this is an inherent problem with the ConcurrentSkipListSet, are there any other thread-safe data structures that can give me reasonably performant insertion and sorting times for unique objects?


原文:https://stackoverflow.com/questions/37310754
更新时间:2023-11-03 13:11

最满意答案

事实证明,我没有正确理解Keppler架构。 正如Greg Smith上面的评论中指出的那样,Keppler可以配置为具有8个字节的32个共享存储体。 在这种情况下,使用cudaDeviceSetSharedMemConfig( cudaSharedMemBankSizeEightByte ) ,共享内存布局如下所示:

bank:  B0   B1   B2   B3   B4    ..   B31
       ----------------------------------
index: D00  D01  D02  D03  D04   ..   D31
       D32  D33  D34  D35  D36   ..   D63   

现在,对于我的简单示例(使用itot=16 ),在一个warp中处理对例如前两行( threadIdx.y=0threadIdx.y=1 )的共享内存的写入/读取。 这意味着对于threadIdx.y=0D00..D15存储在B0..B15 ,则存在两个双精度的填充,之后在相同的变形值D18..D33中存储在B18..B31+B00..B01 ,导致B00-B01发生银行冲突。 如果没有填充( ng=0 ),第一行将写入D00..D15中的B00..B15 ,即D00..D15B00..B15中的第二行,因此不会发生库冲突。

对于blockDim.x>=32的线程块,不应该出现问题。 例如,对于itot=32blockDim.x=32ng=2 ,第一行存储在存储体B00..B31 ,然后存储两个单元格填充,第二行存储在B02..B31+B00..B01等中。


It turns out that I didn’t understand the Keppler architecture correctly. As pointed out in one of the comments above by Greg Smith, Keppler can be configured to have 32 shared memory banks of 8 bytes. In such a case, using cudaDeviceSetSharedMemConfig( cudaSharedMemBankSizeEightByte ), the shared memory layout looks like:

bank:  B0   B1   B2   B3   B4    ..   B31
       ----------------------------------
index: D00  D01  D02  D03  D04   ..   D31
       D32  D33  D34  D35  D36   ..   D63   

Now, for my simple example (using itot=16), the writing/reading to/from shared memory on e.g. the first two rows (threadIdx.y=0, threadIdx.y=1) is handled within one warp. This means that for threadIdx.y=0 values D00..D15 are stored in B0..B15, then there is a padding of two doubles, after which within the same warp values D18..D33 are stored in B18..B31+B00..B01, which causes a bank conflict on B00-B01. Without the padding (ng=0) the first row is written to D00..D15 in B00..B15, the second row in D16..D31 in B16..B31, so no bank conflict occurs.

For a thread block of blockDim.x>=32 the problem shouldn’t occur. For example, for itot=32, blockDim.x=32, ng=2, the first row is stored in banks B00..B31, then two cells padding, second row in B02..B31+B00..B01, etc.

相关问答

更多
  • 对于nvidia(和amd),gpus本地内存分为内存块。 每个银行一次只能处理一个数据集,所以如果一半warp尝试从/向同一个银行加载/存储数据,那么访问必须被序列化(这是一个银行冲突)。 对于gt200 gpus,有16个银行(32个银行为费米),16个银行或32个银行为AMD gpus(57xx或更高:32,所有以下:16)),它们与32位的粒度交错(所以字节0-3在银行1中的银行1,4-7,银行1中的...,64-69等)。 为了更好的可视化,它基本上看起来像这样: Bank | 1 ...
  • 你实际上有一个结构数组(AoS)。 这对于GPU编程来说是规范的。 您可以使用标准AoS-> SoA数据重组方法来修复访问,以便相邻线程访问相邻元素(这将防止存储体冲突)。 以较大的块加载数据,例如重组您的结构,使其可以表示4个float4数量而不是16 float数量。 编译器可能能够将负载组织成float4加载,这将减少银行冲突。 如果你真的需要两种访问方法,你甚至可以在结构中使用union。 根据评论中的问题,让我们看出第二种情况。 对于每个结构16个float数量,无论是存储为float数组还是fl ...
  • 当我编译你现在在linux上的代码时,我得到以下警告: t614.cu(55): warning: __shared__ memory variable with non-empty constructor or destructor (potential race between threads) 这种警告不应该被忽略。 它与这行代码相关联: __shared__ double3c blockmean[THREADS_PER_BLOCK]; 由于存储在共享内存中的这些对象(通过构造函数)的初始化将以 ...
  • 让我们来看看它产生的ptx。 //Declare some registers .reg .s32 %r<5>; .reg .s64 %rd<4>; // demoted variable .shared .align 4 .u32 _Z6kernelv$__cuda_local_var_35411_30_non_const_mywarp; //load tid in register r1 mov.u32 %r1, %tid.x; //multiple tid ...
  • 正如@RobertHarvey所说,它被记录在案。 编程指南指出了16个银行的计算能力1.x ,以及32个银行的计算能力2.x和3.x。 因此,您可以根据设备属性中返回的计算能力(主要版本)做出任何决定。 cuda在线文档的常用链接包含在cuda标签的info链接中。 As @RobertHarvey says, it's documented. The programming guide indicates 16 banks for compute capability 1.x, and 32 banks ...
  • tl; dr:使用与32位值相同的交错类型。 在晚于开普勒的微体系结构(至Volta)上,我们理论上可以得到的最好结果是2个共享内存事务,用于读取单个64位值的完整内存事务(因为单个事务最多可为每个通道提供32位)。 在实践中,您可以通过您为32位数据描述的类似布局模式来实现这一点。 也就是说,对于T* arr , i有通道i读取idx元素为T[idx + i * 32] 。 这将编译,以便发生两个事务: 较低的16个通道从T中的前32 * 4个字节获得它们的数据(利用所有的库) 较高的16从T中的连续32 ...
  • 事实证明,我没有正确理解Keppler架构。 正如Greg Smith上面的评论中指出的那样,Keppler可以配置为具有8个字节的32个共享存储体。 在这种情况下,使用cudaDeviceSetSharedMemConfig( cudaSharedMemBankSizeEightByte ) ,共享内存布局如下所示: bank: B0 B1 B2 B3 B4 .. B31 ---------------------------------- index: D00 ...
  • Nsight Visual Studio Edition CUDA调试器有几个选项来控制可变监视窗口中出现的表达式的评估和可视化。 阵列扩展的默认设置为64.限制是为了避免限制评估大型阵列的成本。 要更改设置 从顶级Nsight菜单执行命令Options ... 在NVIDIA Nsight选项对话框中 在左侧窗格中选择调试器 在右侧窗格中,将Max array expansion elements的设置更改为128 您的用例的另一种解决方案是打开四个内存窗口中的一个并配置columns = 64和type ...
  • 因为SM可以由于其他因素(例如不同的分支逻辑)而重放指令。 因此,我可以假设60%的代码由于分支而重新发布,20%由于全局内存而重新发布。 你可以发一个片段吗? 从Cuda 4.0 Profiler的F1帮助菜单中: 重播指令(%)这给出了在内核执行期间重放的指令的百分比。 重放指令是硬件实际发出的指令数与内核要执行的指令数之间的差异。 理想情况下,这应该为零。 计算为100 *(发出指令 - 执行指令)/发出指令 全局内存重放(%)由于全局内存访问而导致的重放指令的百分比。 这被计算为100 *(l1全局 ...
  • 从我所看到的,在循环迭代之间的应用程序中可能存在危险。 对循环迭代frame_idx+1 deltas[lex_index_block]的写入可以映射到与迭代时不同线程中的deltas[lex_index_2D(threadIdx.x, threadIdx.y -1, blockDim.x)]的读取相同的位置frame_idx 。 这两个访问是无序的,结果是不确定的。 尝试使用cuda-memcheck --tool racecheck运行应用程序cuda-memcheck --tool racecheck ...

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。