/// <summary> /// Executes a CUFTT transorm as defined by the cufftType. /// This method does an in‐place transform.<para/> /// This method is only valid for transform types where transorm direction is implicitly /// given by the type (i.e. not C2C and not Z2Z) /// </summary> /// <param name="iodata"></param> public void Exec(CUdeviceptr iodata) { switch (_type) { case cufftType.R2C: res = CudaFFTNativeMethods.cufftExecR2C(_handle, iodata, iodata); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftExecR2C", res)); break; case cufftType.C2R: res = CudaFFTNativeMethods.cufftExecC2R(_handle, iodata, iodata); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftExecC2R", res)); break; case cufftType.D2Z: res = CudaFFTNativeMethods.cufftExecD2Z(_handle, iodata, iodata); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftExecD2Z", res)); break; case cufftType.Z2D: res = CudaFFTNativeMethods.cufftExecZ2D(_handle, iodata, iodata); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftExecZ2D", res)); break; default: throw new ArgumentException("For transformation not of type R2C, C2R, D2Z or Z2D, you must specify a transform direction."); } if (res != cufftResult.Success) { throw new CudaFFTException(res); } }
/// <summary> /// Associates a CUDA stream with a CUFFT plan. All kernel launches /// made during plan execution are now done through the associated /// stream, enabling overlap with activity in other streams (for example, /// data copying). The association remains until the plan is destroyed or /// the stream is changed with another call to SetStream(). /// </summary> /// <param name="stream">A valid CUDA stream created with cudaStreamCreate() (or 0 for the default stream)</param> public void SetStream(CUstream stream) { res = CudaFFTNativeMethods.cufftSetStream(_handle, stream); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftSetStream", res)); if (res != cufftResult.Success) { throw new CudaFFTException(res); } }
/// <summary> /// configures the layout of CUFFT output in FFTW‐compatible modes. /// When FFTW compatibility is desired, it can be configured for padding /// only, for asymmetric complex inputs only, or to be fully compatible. /// </summary> /// <param name="mode">The <see cref="Compatibility"/> option to be used</param> public void SetCompatibilityMode(Compatibility mode) { res = CudaFFTNativeMethods.cufftSetCompatibilityMode(_handle, mode); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftSetCompatibilityMode", res)); if (res != cufftResult.Success) { throw new CudaFFTException(res); } }
/// <summary> /// SetWorkArea() overrides the work area pointer associated with a plan. /// If the work area was auto-allocated, CUFFT frees the auto-allocated space. The /// cufftExecute*() calls assume that the work area pointer is valid and that it points to /// a contiguous region in device memory that does not overlap with any other work area. If /// this is not the case, results are indeterminate. /// </summary> /// <param name="workArea"></param> public void SetWorkArea(CUdeviceptr workArea) { res = CudaFFTNativeMethods.cufftSetWorkArea(_handle, workArea); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftSetWorkArea", res)); if (res != cufftResult.Success) { throw new CudaFFTException(res); } }
/// <summary> /// Once plan generation has been done, either with the original API or the extensible API, /// this call returns the actual size of the work area required to support the plan. Callers /// who choose to manage work area allocation within their application must use this call /// after plan generation, and after any cufftSet*() calls subsequent to plan generation, if /// those calls might alter the required work space size. /// </summary> /// <returns></returns> public SizeT GetActualSize() { SizeT size = new SizeT(); res = CudaFFTNativeMethods.cufftGetSize(_handle, ref size); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftGetSize", res)); if (res != cufftResult.Success) { throw new CudaFFTException(res); } return(size); }
/// <summary> /// During plan execution, CUFFT requires a work area for temporary storage of /// intermediate results. This call returns an estimate for the size of the work area required, /// given the specified parameters, and assuming default plan settings. Note that changing /// some plan settings, such as compatibility mode, may alter the size required for the work /// area. /// </summary> /// <param name="nx">The transform size in the x dimension</param> /// <param name="ny">The transform size in the y dimension</param> /// <param name="nz">The transform size in the z dimension</param> /// <param name="type">The transform data type (e.g., CUFFT_C2C for single /// precision complex to complex)</param> /// <returns></returns> public static SizeT EstimateSize(int nx, int ny, int nz, cufftType type) { SizeT size = new SizeT(); cufftResult res = CudaFFTNativeMethods.cufftEstimate3d(nx, ny, nz, type, ref size); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftEstimate3d", res)); if (res != cufftResult.Success) { throw new CudaFFTException(res); } return(size); }
// /// <summary> ///// Creates a new 3D FFT plan (old API) // /// </summary> // /// <param name="nx">The transform size in the X dimension</param> // /// <param name="ny">The transform size in the Y dimension</param> // /// <param name="nz">The transform size in the Z dimension</param> // /// <param name="type">The transform data type (e.g., R2C for real to complex)</param> // /// <param name="mode">The <see cref="Compatibility"/> option to be used</param> // public CudaFFTPlan3D(int nx, int ny, int nz, cufftType type, Compatibility mode) // : this(nx, ny, nz, type) // { // SetCompatibilityMode(mode); // } // /// <summary> ///// Creates a new 3D FFT plan (old API) // /// </summary> // /// <param name="nx">The transform size in the X dimension</param> // /// <param name="ny">The transform size in the Y dimension</param> // /// <param name="nz">The transform size in the Z dimension</param> // /// <param name="type">The transform data type (e.g., R2C for real to complex)</param> // /// <param name="stream">A valid CUDA stream created with cudaStreamCreate() (or 0 for the default stream)</param> // /// <param name="mode">The <see cref="Compatibility"/> option to be used</param> // public CudaFFTPlan3D(int nx, int ny, int nz, cufftType type, CUstream stream, Compatibility mode) // : this(nx, ny, nz, type) // { // SetStream(stream); // SetCompatibilityMode(mode); // } /// <summary> /// Creates a new 3D FFT plan (new API) /// </summary> /// <param name="handle">cufftHandle object</param> /// <param name="nx">The transform size in the X dimension</param> /// <param name="ny">The transform size in the Y dimension</param> /// <param name="nz">The transform size in the Z dimension</param> /// <param name="type">The transform data type (e.g., C2R for complex to real)</param> /// <param name="size"></param> public CudaFFTPlan3D(cufftHandle handle, int nx, int ny, int nz, cufftType type, ref SizeT size) { _handle = handle; _nx = nx; _type = type; res = CudaFFTNativeMethods.cufftMakePlan2d(_handle, nx, ny, type, ref size); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftMakePlan2d", res)); if (res != cufftResult.Success) { throw new CudaFFTException(res); } }
/// <summary> /// Creates a new 1D FFT plan (old API) /// </summary> /// <param name="nx">The transform size (e.g., 256 for a 256-point FFT)</param> /// <param name="type">The transform data type (e.g., C2C for complex to complex)</param> /// <param name="batch">Number of transforms of size nx</param> public CudaFFTPlan1D(int nx, cufftType type, int batch) { _handle = new cufftHandle(); _nx = nx; _type = type; _batch = batch; res = CudaFFTNativeMethods.cufftPlan1d(ref _handle, nx, type, batch); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftPlan1d", res)); if (res != cufftResult.Success) { throw new CudaFFTException(res); } }
/// <summary> /// Creates only an opaque handle, and allocates small data structures on the host. The /// cufftMakePlan*() calls actually do the plan generation. It is recommended that /// cufftSet*() calls, such as cufftSetCompatibilityMode(), that may require a plan /// to be broken down and re-generated, should be made after cufftCreate() and before /// one of the cufftMakePlan*() calls. /// </summary> /// <returns></returns> public static cufftHandle Create() { cufftHandle handle = new cufftHandle(); cufftResult res = CudaFFTNativeMethods.cufftCreate(ref handle); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftCreate", res)); if (res != cufftResult.Success) { throw new CudaFFTException(res); } return(handle); }
/// <summary> /// Creates a new 3D FFT plan (old API) /// </summary> /// <param name="nx">The transform size in the X dimension</param> /// <param name="ny">The transform size in the Y dimension</param> /// <param name="nz">The transform size in the Z dimension</param> /// <param name="type">The transform data type (e.g., R2C for real to complex)</param> public CudaFFTPlan3D(int nx, int ny, int nz, cufftType type) { _handle = new cufftHandle(); _nx = nx; _ny = ny; _nz = nz; _type = type; res = CudaFFTNativeMethods.cufftPlan3d(ref _handle, nx, ny, nz, type); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftPlan3d", res)); if (res != cufftResult.Success) { throw new CudaFFTException(res); } }
/// <summary> /// For IDisposable /// </summary> /// <param name="fDisposing"></param> protected virtual void Dispose(bool fDisposing) { if (fDisposing && !disposed) { //Ignore if failing res = CudaFFTNativeMethods.cufftDestroy(_handle); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftDestroy", res)); disposed = true; } if (!fDisposing && !disposed) { Debug.WriteLine(String.Format("ManagedCUDA not-disposed warning: {0}", this.GetType())); } }
/// <summary> /// SetAutoAllocation() indicates that the caller intends to allocate and manage /// work areas for plans that have been generated. CUFFT default behavior is to allocate /// the work area at plan generation time. If cufftSetAutoAllocation() has been called /// with autoAllocate set to "false" prior to one of the cufftMakePlan*() calls, CUFFT /// does not allocate the work area. This is the preferred sequence for callers wishing to /// manage work area allocation. /// </summary> /// <param name="autoAllocate"></param> public void SetAutoAllocation(bool autoAllocate) { int auto = 0; if (autoAllocate) { auto = 1; } res = CudaFFTNativeMethods.cufftSetAutoAllocation(_handle, auto); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftSetAutoAllocation", res)); if (res != cufftResult.Success) { throw new CudaFFTException(res); } }
/// <summary> /// Executes a CUFTT transorm as defined by the cufftType. /// This method does an in‐place transform. /// </summary> /// <param name="iodata"></param> /// <param name="direction">Only unsed for transformations where direction is not implicitly given by type</param> public void Exec(CUdeviceptr iodata, TransformDirection direction) { switch (_type) { case cufftType.R2C: res = CudaFFTNativeMethods.cufftExecR2C(_handle, iodata, iodata); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftExecR2C", res)); break; case cufftType.C2R: res = CudaFFTNativeMethods.cufftExecC2R(_handle, iodata, iodata); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftExecC2R", res)); break; case cufftType.C2C: res = CudaFFTNativeMethods.cufftExecC2C(_handle, iodata, iodata, direction); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftExecC2C", res)); break; case cufftType.D2Z: res = CudaFFTNativeMethods.cufftExecD2Z(_handle, iodata, iodata); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftExecD2Z", res)); break; case cufftType.Z2D: res = CudaFFTNativeMethods.cufftExecZ2D(_handle, iodata, iodata); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftExecZ2D", res)); break; case cufftType.Z2Z: res = CudaFFTNativeMethods.cufftExecZ2Z(_handle, iodata, iodata, direction); Debug.WriteLine(String.Format("{0:G}, {1}: {2}", DateTime.Now, "cufftExecZ2Z", res)); break; default: break; } if (res != cufftResult.Success) { throw new CudaFFTException(res); } }