1 回答
TA贡献1893条经验 获得超10个赞
那么,您需要了解编组的工作原理
在 .Net 中创建的对象和数组(甚至常驻数组)都是宿主。然后我们在内核执行之前编组它们(固定主机内存,分配设备内存并将主机复制到设备)。
对于 float[],这将自动完成
对于 IntPtr,我们什么都不做,用户必须确保 IntPtr 是包含数据的有效设备指针
对于常驻数组,我们什么都不做,用户在想要来回获取数据时必须手动调用 RefreshDevice() 和 RefreshHost。
支持混合 ResidentArray 和 float[],如生成的 dll 的屏幕截图所示:
不支持的是:混合托管类型和 IntPtr。
这是您的代码工作的完整版本,并返回正确的结果:
using Hybridizer.Runtime.CUDAImports;
using System;
using System.Runtime.InteropServices;
namespace SimpleMetadataDecorator
{
class Program
{
[EntryPoint]
public static void Total(FloatResidentArray a, int N, float[] total)
{
var cache = new SharedMemoryAllocator<float>().allocate(blockDim.x);
int tid = threadIdx.x + blockDim.x * blockIdx.x;
int cacheIndex = threadIdx.x;
float sum = 0f;
while (tid < N)
{
sum = sum + a[tid];
tid += blockDim.x * gridDim.x;
}
cache[cacheIndex] = sum;
CUDAIntrinsics.__syncthreads();
int i = blockDim.x / 2;
while (i != 0)
{
if (cacheIndex < i)
{
cache[cacheIndex] = cache[cacheIndex] + cache[cacheIndex + i];
}
CUDAIntrinsics.__syncthreads();
i >>= 1;
}
if (cacheIndex == 0)
{
AtomicExpr.apply(ref total[0], cache[0], (x, y) => x + y);
}
}
static void Main(string[] args)
{
const int N = 1024 * 1024 * 32;
FloatResidentArray arr = new FloatResidentArray(N);
float[] res = new float[1];
for (int i = 0; i < N; ++i)
{
arr[i] = 1.0F;
}
arr.RefreshDevice();
var runner = HybRunner.Cuda();
cudaDeviceProp prop;
cuda.GetDeviceProperties(out prop, 0);
runner.SetDistrib(16 * prop.multiProcessorCount, 1, 128, 1, 1, 128 * sizeof(float));
var wrapped = runner.Wrap(new Program());
runner.saveAssembly();
cuda.ERROR_CHECK((cudaError_t)(int)wrapped.Total(arr, N, res));
cuda.ERROR_CHECK(cuda.DeviceSynchronize());
Console.WriteLine(res[0]);
}
}
}
- 1 回答
- 0 关注
- 97 浏览
添加回答
举报