C# 如果我使用其他GPU,为什么我的OpenCL功能不能工作?

C# 如果我使用其他GPU,为什么我的OpenCL功能不能工作?,c#,arrays,opencl,C#,Arrays,Opencl,我用我的GPU控制大阵列,在我的第一台PC(有AMD RX 570)上一切正常,但在第二台PC(Nvidia 920m)上,我的功能不起作用,我的应用程序崩溃,因为复制的阵列被0填充 这是我的函数(我添加了prinf来检查我的程序是否实际在使用它): kernelvoidarraycopy(全局uchar*bufferIn,int-inOffset, 全局uchar*缓冲输出,整数输出偏移) { int index=get_global_id(0); bufferOut[index+outOff

我用我的GPU控制大阵列,在我的第一台PC(有AMD RX 570)上一切正常,但在第二台PC(Nvidia 920m)上,我的功能不起作用,我的应用程序崩溃,因为复制的阵列被0填充

这是我的函数(我添加了prinf来检查我的程序是否实际在使用它):

kernelvoidarraycopy(全局uchar*bufferIn,int-inOffset,
全局uchar*缓冲输出,整数输出偏移)
{
int index=get_global_id(0);
bufferOut[index+outOffset]=bufferIn[index+inooffset];
printf(“它起作用了!”);
}
我不知道为什么
Cloo
没有给我一个异常、警告或其他任何东西

在调试应用程序时,我发现了一些有关图形卡的数据:

谢谢大家,对不起我的英语不好

编辑:

我创建了一个通过UDP套接字发送图像的程序,这些图像可以达到200KB以上,因此我应该在多个数据包中发送它们,并在客户端应用程序中以相同的顺序重建它们

由于我使用的是
sockets
,所以这些数组将是字节数组(
byte[]
),即
uchar*

我使用Nodaways重建这些图像,由于阵列的大小,重建速度非常慢。因此,我使用
Cloo
编写了一个函数,它接受5个参数(比如
System.Array.Copy
):

  • bufferIn(源阵列)
  • inOffset(开始读取值的源索引)
  • 缓冲输出(目标阵列)
  • 超出偏移量(开始设置值的目的地索引)
  • 长度(要复制的元素数)
public void GPUCopy(字节[]bufferIn,int-inOffset,字节[]bufferOut,int-outOffset,int-lenght)
{
ComputeBuffer originBuffer,destBuffer;
originBuffer=新的ComputeBuffer(上下文,
ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.UseHostPointer,bufferIn);
destBuffer=newcomputebuffer(上下文,
ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.UseHostPointer,bufferOut);
SetMemoryArgument(0,originBuffer);
SetValueArgument(1,inOffset);
SetMemoryArgument(2,destBuffer);
SetValueArgument(3,outOffset);
Execute(kernel,new long[]{0},new long[]{lenght},null,new ComputeEventList());
queue.Finish();
}
正如我之前所说,这与我的RX 570配合得很好,并且在我的920m上没有错误

完整类源代码如下:

类GPU
{
私有ComputeCommandQueue队列;
私有计算上下文;
私有计算机内核;
私有字符串数组复制
{
得到
{
返回@”
内核void ArrayCopy(全局uchar*bufferIn、int-inOffset、全局uchar*bufferOut、int-outOffset)
{
int index=get_global_id(0);
bufferOut[index+outOffset]=bufferIn[index+inooffset];
}";
}
}
公共GPU()
{
context=new ComputeContext(ComputeDeviceTypes.Gpu,new ComputeContextPropertyList(ComputePlatform.Platforms[0]),null,IntPtr.Zero);
队列=新的ComputeCommandQueue(上下文,context.Devices[0],ComputeCommandQueueFlags.None);
var程序=新的计算程序(上下文,ArrayCopy);
Build(null,null,null,IntPtr.Zero);
kernel=program.CreateKernel(“ArrayCopy”);
}
public void GPUCopy(字节[]bufferIn,int-inOffset,字节[]bufferOut,int-outOffset,int-lenght)
{
ComputeBuffer originBuffer,destBuffer;
originBuffer=新的ComputeBuffer(上下文,
ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.UseHostPointer,bufferIn);
destBuffer=newcomputebuffer(上下文,
ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.UseHostPointer,bufferOut);
SetMemoryArgument(0,originBuffer);
SetValueArgument(1,inOffset);
SetMemoryArgument(2,destBuffer);
SetValueArgument(3,outOffset);
Execute(kernel,new long[]{0},new long[]{lenght},null,new ComputeEventList());
queue.Finish();
}
}

您在问题中提供的信息非常少,但我能想到一些您需要检查或尝试的东西,而评论对此有些尴尬,因此这里有一个“答案”:

  • 您的上下文符合哪个版本的OpenCL?在OpenCL1.0中,字节寻址不是内置的,一次只能复制一个字节(
    uchar
    )。因此,如果您的上下文是OpenCL1.0上下文,请检查您的设备是否支持,并在内核中启用它。(在OpenCL1.1及更新版本中,您不需要这样做。)

  • 如果以上不是问题的原因,我希望主机端会返回一些错误。你确定你检查的足够了吗?我不熟悉cloo包装器,似乎没有任何文档(?),但在普通OpenCL中,几乎每个主机函数都会返回某种类型的结果代码,如果不检查并处理它,通常会导致您看到的那种行为
  • 如果您的内核真的像您所发布的那样,这不仅仅是一个简化的示例:对于复制缓冲区子范围,您可能应该使用,它使用设备的DMA引擎(如果可用),而不是自定义内核。如果这在任何OpenCL实现中都比较慢,并且在某些情况下会更快,我会非常惊讶

不确定是否稍后,但我认为nvidia不支持opencl 1.2中的
printf
-请删除它并重新测试。@Doq或者我的第一次尝试没有printf,没有任何更改。然后需要更多信息