static void WorkaroundKnownIssue(CudaAccelerator accelerator, CuFFTAPI api) { // The CUDA release notes for 11.2 to 11.3 (inclusive) contains a known issue: // - cuFFT planning and plan estimation functions may not restore correct // context affecting CUDA driver API applications. // // This workaround restores the accelerator context so that deallocation of // the memory buffers can be performed on the correct context. // // Based on the versions of CuFFT released, apply workaround to CuFFT v10.4.x. // // Release 11.1.1 CuFFT v10.3.0.105 // Release 11.2 CuFFT v10.4.0.72 // Release 11.3 CuFFT v10.4.2.58 // Release 11.4 CuFFT v10.5.0.43 // CuFFTException.ThrowIfFailed( api.GetProperty(LibraryPropertyType.MAJOR_VERSION, out var major)); CuFFTException.ThrowIfFailed( api.GetProperty(LibraryPropertyType.MINOR_VERSION, out var minor)); if (major == 10 && minor == 4) { CudaException.ThrowIfFailed( CudaAPI.CurrentAPI.SetCurrentContext(accelerator.NativePtr)); } }
// Use the low-level CuFFT API to perform an inverse transform. static void DoInversePlan( CudaAccelerator accelerator, CuFFTAPI api, Complex[] input, out Complex[] output) { using var stream = accelerator.CreateStream() as CudaStream; using var inputBuffer = accelerator.Allocate1D(input); using var outputBuffer = accelerator.Allocate1D <Complex>(input.Length); CuFFTException.ThrowIfFailed( api.Plan1D( out var plan, input.Length, CuFFTType.CUFFT_Z2Z, batch: 1)); try { CuFFTException.ThrowIfFailed( api.SetStream(plan, stream)); CuFFTException.ThrowIfFailed( api.ExecZ2Z( plan, inputBuffer.View.BaseView, outputBuffer.View.BaseView, CuFFTDirection.INVERSE)); output = outputBuffer.GetAsArray1D(stream); } finally { CuFFTException.ThrowIfFailed( api.Destroy(plan)); } WorkaroundKnownIssue(accelerator, api); // Scale the output to obtain the inverse. for (var i = 0; i < output.Length; i++) { output[i] /= output.Length; } Console.WriteLine("Inverse Values:"); for (var i = 0; i < output.Length; i++) { Console.WriteLine($" [{i}] = {output[i].Real}"); } }
/// <summary> /// Constructs a new instance to wrap a cuFFT plan. /// </summary> public CuFFTPlan(CuFFTAPI api, IntPtr plan) { API = api; PlanHandle = plan; }
/// <summary> /// Constructs a new CuFFT instance. /// </summary> public CuFFT(CuFFTAPIVersion?version) { API = CuFFTAPI.Create(version); }