缺少8位变量的CUDA内联PTX约束字母,以便禁用8位变量(bool)的一级缓存

缺少8位变量的CUDA内联PTX约束字母,以便禁用8位变量(bool)的一级缓存,cuda,inline-assembly,cpu-cache,type-constraints,ptx,Cuda,Inline Assembly,Cpu Cache,Type Constraints,Ptx,导言 在中,我们可以学习如何为单个变量禁用一级缓存。 以下是公认的答案: 如上所述,您可以使用内联PTX,以下是一个示例: 通过将.f64替换为.f32(float)或.s32,可以很容易地改变这一点 (int)等,对于“=d”(浮点)或 “=r”(int)等。请注意,(addr)-“l”之前的最后一个约束- 表示64位寻址,如果使用32位寻址,则 应该是“r” 现在,我想加载一个布尔值(1字节)而不是浮点值。所以,我想我可以做这样的事情(对于架构>=sm_20): ,其中“?”应为布尔值的适当

导言

在中,我们可以学习如何为单个变量禁用一级缓存。 以下是公认的答案:

如上所述,您可以使用内联PTX,以下是一个示例:

通过将.f64替换为.f32(float)或.s32,可以很容易地改变这一点 (int)等,对于“=d”(浮点)或 “=r”(int)等。请注意,(addr)-“l”之前的最后一个约束- 表示64位寻址,如果使用32位寻址,则 应该是“r”

现在,我想加载一个布尔值(1字节)而不是浮点值。所以,我想我可以做这样的事情(对于架构>=sm_20):

,其中“?”应为布尔值的适当约束字母,分别为8位无符号整数(从中,我推断出这一点,因为注意到对于>=sm_20,“u8”用于布尔值)。然而,我在nvidias文档“”中找不到合适的约束函(第6页列出了一些约束函)。所以我的问题是:

问题

  • 是否有任何类型的CUDA内联PTX约束字母:

    • 布尔值
    • 无符号8位整数
    • 或evtl 8位二进制变量
  • 如果没有,我可以在我的情况下做什么(在引言中解释)?-简短讨论的参数“b0”、“b1”等是否有帮助

  • 提前非常感谢您的帮助或意见

    更新

    我还需要一个从二级缓存而不是全局内存读取的存储函数,即存储函数,它是对上述ld_gbl_cg函数的补充(只有在我拥有该函数后,我才能完全验证njuffa的答案是否有效)。 根据njuffa的回答,我的最佳猜测如下:

    __device__ __forceinline__ void st_gbl_cg (const bool *addr, bool t)
    {
    #if defined(__LP64__) || defined(_WIN64)
        asm ("st.global.cg.u8 [%0], %1;" : "=l"(addr) : "h"((short)t));
    #else
        asm ("st.global.cg.u8 [%0], %1;" : "=r"(addr) : "h"((short)t));
    #endif
    }
    
    但是,编译器会发出警告“参数“addr”已设置但从未使用”,并且程序在运行时失败,出现“未指定的启动失败”。 我还尝试使用.u16而不是.u8,因为我不知道它到底指的是什么。但结果是一样的

    (附加信息)PTX 3.1文档中的以下段落似乎对这个问题很重要:

    5.2.2子字大小的限制使用.u8、.s8和.b8指令类型仅限于ld、st和cvt指令。这个 .f16浮点类型仅允许在与之间的转换中使用 .f32和.f64类型。所有浮点指令仅在 .f32和.f64类型。为方便起见,请参阅ld、st和cvt说明 允许源和目标数据操作数的宽度大于 指令类型大小,以便加载、存储窄值, 并使用规则宽度寄存器进行转换。例如,8位或 当需要时,16位值可直接保存在32位或64位寄存器中 正在加载、存储或转换为其他类型和大小的

    根据文档“在CUDA中使用内联PTX”,字节大小的操作数没有限制。据我所知,最接近所需功能的方法是通过中间的“short”移动数据。这将导致一条额外的SASS指令,用于从“short”转换为“bool”

    __device__ __forceinline__ bool ld_gbl_cg (const bool *addr)
    {
        short t;
    #if defined(__LP64__) || defined(_WIN64)
        asm ("ld.global.cg.u8 %0, [%1];" : "=h"(t) : "l"(addr));
    #else
        asm ("ld.global.cg.u8 %0, [%1];" : "=h"(t) : "r"(addr));
    #endif
        return (bool)t;
    }
    

    根据第5.2节,
    .u8
    是无符号8位整数。我认为没有布尔型内置类型。@罗伯特-谢谢你的评论。是的,我知道。u8代表PTX中的8位无符号整数。但是,我在CUDA内联PTX中找不到与PTX中的.u8寄存器相对应的约束字母。即,我不知道用什么字母替换上述代码中的“?”(引言中的第二个代码)。例如,如果我将其替换为“r”,则会出现以下错误:“错误:asm操作数类型大小(1)与约束“r”隐含的类型/大小不匹配。”。出现此错误是因为r代表4字节无符号整数,而不是1字节无符号整数…文档“在CUDA中使用内联PTX”列出了可用的约束。字节大小的操作数没有限制。这似乎是有道理的,因为没有字节大小的寄存器可以绑定字节大小的变量。尝试加载到用.reg.u32声明的32位临时寄存器中,并使用“=r”约束。非常感谢您的回答!它似乎起作用了!(额外的转换对我来说并不重要:))要知道它是否确实有效,我需要一个与上述ld_gbl_cg函数互补的存储函数。我在上面的问题中添加了这个(见更新)。如果你能帮我解决这个问题,那就太棒了!加载有缓存模式后缀,我不知道存储也有。存储函数未编译的原因是绑定不正确。%0和%1都是读取绑定,因此addr应该用“l”/“r”,no“=l”/“=r”绑定。你可能需要一个“记忆”打击器。我没有时间去了解细节,也没有时间在接下来的两天内尝试。非常感谢你的评论。基于此,我会尝试一下(但PTX对我来说确实是一片陌生的土地)。如果我没有误解PTX 3.1文档(),“缓存模式后缀”确实存在:表84,第120页列出了“内存存储指令的缓存运算符”。如果我在“st_gbl_cg”函数中使用以下asm语句,它编译时没有警告,并允许将数据存储到全局位置(对于64位地址情况):
    asm(“st.global.cg.u8[%0],%1;::“l”(addr),“h”((short)t))
    唯一我还不确定的是,“ld_gbl_cg”和“st_gbl_cg”是否真的作用于二级缓存而不是全局内存。事实上,使用缓存操作符.cg作为“ld_gbl_cg”和“st_gbl_cg”到目前为止给我的性能与使用.cv(load volatile)和.wt相同(写通)。也就是说,两者似乎都是从同一个位置读取的…我做了一些测试
    __device__ __forceinline__ void st_gbl_cg (const bool *addr, bool t)
    {
    #if defined(__LP64__) || defined(_WIN64)
        asm ("st.global.cg.u8 [%0], %1;" : "=l"(addr) : "h"((short)t));
    #else
        asm ("st.global.cg.u8 [%0], %1;" : "=r"(addr) : "h"((short)t));
    #endif
    }
    
    __device__ __forceinline__ bool ld_gbl_cg (const bool *addr)
    {
        short t;
    #if defined(__LP64__) || defined(_WIN64)
        asm ("ld.global.cg.u8 %0, [%1];" : "=h"(t) : "l"(addr));
    #else
        asm ("ld.global.cg.u8 %0, [%1];" : "=h"(t) : "r"(addr));
    #endif
        return (bool)t;
    }