yum-mirror/VkFFT

git clone https://git.yummers.dev/yum-mirror/VkFFT

Dmitrii TolmachevVkFFT v1.3.4 release -Stable release that incorporates all the v1.3.3 bugfixes - no new functionality in this release -Tests reference: https://github.com/vincefn/pyvkfft/issues/32#issuecomment-1904238557066a17c

master
38.9 KiB1060 linesraw
1#include <vector>
2#include <memory>
3#include <string.h>
4#include <chrono>
5#include <thread>
6#include <iostream>
7#include <algorithm>
8#define __STDC_FORMAT_MACROS
9#include <inttypes.h>
10#if(VKFFT_BACKEND==0)
11#include "vulkan/vulkan.h"
12#include "glslang_c_interface.h"
13#elif(VKFFT_BACKEND==1)
14#include <cuda.h>
15#include <cuda_runtime.h>
16#include <nvrtc.h>
17#include <cuda_runtime_api.h>
18#include <cuComplex.h>
19#elif(VKFFT_BACKEND==2)
20#ifndef __HIP_PLATFORM_HCC__
21#define __HIP_PLATFORM_HCC__
22#endif
23#include <hip/hip_runtime.h>
24#include <hip/hiprtc.h>
25#include <hip/hip_runtime_api.h>
26#include <hip/hip_complex.h>
27#elif(VKFFT_BACKEND==3)
28#ifndef CL_USE_DEPRECATED_OPENCL_1_2_APIS
29#define CL_USE_DEPRECATED_OPENCL_1_2_APIS
30#endif
31#ifdef __APPLE__
32#include <OpenCL/opencl.h>
33#else
34#include <CL/cl.h>
35#endif 
36#elif(VKFFT_BACKEND==4)
37#include <ze_api.h>
38#elif(VKFFT_BACKEND==5)
39#ifndef NS_PRIVATE_IMPLEMENTATION
40#define NS_PRIVATE_IMPLEMENTATION
41#endif
42#ifndef CA_PRIVATE_IMPLEMENTATION
43#define CA_PRIVATE_IMPLEMENTATION
44#endif
45#ifndef MTL_PRIVATE_IMPLEMENTATION
46#define MTL_PRIVATE_IMPLEMENTATION
47#endif
48#include "Foundation/Foundation.hpp"
49#include "QuartzCore/QuartzCore.hpp"
50#include "Metal/Metal.hpp"
51#endif
52#include "vkFFT.h"
53#include "utils_VkFFT.h"
54#include "half.hpp"
55#include "user_benchmark_VkFFT.h"
56#include "sample_0_benchmark_VkFFT_single.h"
57#include "sample_1_benchmark_VkFFT_double.h"
58#include "sample_2_benchmark_VkFFT_half.h"
59#include "sample_3_benchmark_VkFFT_single_3d.h"
60#include "sample_4_benchmark_VkFFT_single_3d_zeropadding.h"
61#include "sample_5_benchmark_VkFFT_single_disableReorderFourStep.h"
62#include "sample_6_benchmark_VkFFT_single_r2c.h"
63#include "sample_7_benchmark_VkFFT_single_Bluestein.h"
64#include "sample_8_benchmark_VkFFT_double_Bluestein.h"
65#ifdef VKFFT_USE_DOUBLEDOUBLE_FP128
66#include "sample_9_benchmark_VkFFT_quadDoubleDouble.h"
67#endif
68#include "sample_10_benchmark_VkFFT_single_multipleBuffers.h"
69#ifdef USE_FFTW
70#include "sample_11_precision_VkFFT_single.h"
71#include "sample_12_precision_VkFFT_double.h"
72#include "sample_13_precision_VkFFT_half.h"
73#include "sample_14_precision_VkFFT_single_nonPow2.h"
74#include "sample_15_precision_VkFFT_single_r2c.h"
75#include "sample_16_precision_VkFFT_single_dct.h"
76#include "sample_17_precision_VkFFT_double_dct.h"
77#include "sample_18_precision_VkFFT_double_nonPow2.h"
78#ifdef VKFFT_USE_DOUBLEDOUBLE_FP128
79#include "sample_19_precision_VkFFT_quadDoubleDouble_nonPow2.h"
80#endif
81#endif
82#include "sample_50_convolution_VkFFT_single_1d_matrix.h"
83#include "sample_51_convolution_VkFFT_single_3d_matrix_zeropadding_r2c.h"
84#include "sample_52_convolution_VkFFT_single_2d_batched_r2c.h"
85
86#include "sample_100_benchmark_VkFFT_single_nd_dct.h"
87#include "sample_101_benchmark_VkFFT_double_nd_dct.h"
88#include "sample_1000_benchmark_VkFFT_single_2_4096.h"
89#include "sample_1001_benchmark_VkFFT_double_2_4096.h"
90#include "sample_1002_benchmark_VkFFT_half_2_4096.h"
91#include "sample_1003_benchmark_VkFFT_single_3d_2_512.h"
92#ifdef VKFFT_USE_DOUBLEDOUBLE_FP128
93#include "sample_1004_benchmark_VkFFT_quadDoubleDouble_2_4096.h"
94#endif
95#ifdef USE_cuFFT
96#include "user_benchmark_cuFFT.h"
97#include "sample_0_benchmark_cuFFT_single.h"
98#include "sample_1_benchmark_cuFFT_double.h"
99#include "sample_2_benchmark_cuFFT_half.h"
100#include "sample_3_benchmark_cuFFT_single_3d.h"
101#include "sample_6_benchmark_cuFFT_single_r2c.h"
102#include "sample_7_benchmark_cuFFT_single_Bluestein.h"
103#include "sample_8_benchmark_cuFFT_double_Bluestein.h"
104#include "sample_1000_benchmark_cuFFT_single_2_4096.h"
105#include "sample_1001_benchmark_cuFFT_double_2_4096.h"
106#include "sample_1003_benchmark_cuFFT_single_3d_2_512.h"
107#endif  
108#ifdef USE_rocFFT
109#include "user_benchmark_rocFFT.h"
110#include "sample_0_benchmark_rocFFT_single.h"
111#include "sample_1_benchmark_rocFFT_double.h"
112#include "sample_3_benchmark_rocFFT_single_3d.h"
113#include "sample_6_benchmark_rocFFT_single_r2c.h"
114#include "sample_7_benchmark_rocFFT_single_Bluestein.h"
115#include "sample_8_benchmark_rocFFT_double_Bluestein.h"
116#include "sample_1000_benchmark_rocFFT_single_2_4096.h"
117#include "sample_1001_benchmark_rocFFT_double_2_4096.h"
118#include "sample_1003_benchmark_rocFFT_single_3d_2_512.h"
119#endif 
120#ifdef USE_FFTW
121#include "fftw3.h"
122#endif
123
124VkFFTResult launchVkFFT(VkGPU* vkGPU, uint64_t sample_id, bool file_output, FILE* output, VkFFTUserSystemParameters* userParams) {
125	//Sample Vulkan project GPU initialization.
126	VkFFTResult resFFT = VKFFT_SUCCESS;
127
128#if(VKFFT_BACKEND==0)
129	VkResult res = VK_SUCCESS;
130	//create instance - a connection between the application and the Vulkan library 
131	res = createInstance(vkGPU, sample_id);
132	if (res != 0) {
133		//printf("Instance creation failed, error code: %" PRIu64 "\n", res);
134		return VKFFT_ERROR_FAILED_TO_CREATE_INSTANCE;
135	}
136	//set up the debugging messenger 
137	res = setupDebugMessenger(vkGPU);
138	if (res != 0) {
139		//printf("Debug messenger creation failed, error code: %" PRIu64 "\n", res);
140		return VKFFT_ERROR_FAILED_TO_SETUP_DEBUG_MESSENGER;
141	}
142	//check if there are GPUs that support Vulkan and select one
143	res = findPhysicalDevice(vkGPU);
144	if (res != 0) {
145		//printf("Physical device not found, error code: %" PRIu64 "\n", res);
146		return VKFFT_ERROR_FAILED_TO_FIND_PHYSICAL_DEVICE;
147	}
148	//create logical device representation
149	res = createDevice(vkGPU, sample_id);
150	if (res != 0) {
151		//printf("Device creation failed, error code: %" PRIu64 "\n", res);
152		return VKFFT_ERROR_FAILED_TO_CREATE_DEVICE;
153	}
154	//create fence for synchronization 
155	res = createFence(vkGPU);
156	if (res != 0) {
157		//printf("Fence creation failed, error code: %" PRIu64 "\n", res);
158		return VKFFT_ERROR_FAILED_TO_CREATE_FENCE;
159	}
160	//create a place, command buffer memory is allocated from
161	res = createCommandPool(vkGPU);
162	if (res != 0) {
163		//printf("Fence creation failed, error code: %" PRIu64 "\n", res);
164		return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_POOL;
165	}
166	vkGetPhysicalDeviceProperties(vkGPU->physicalDevice, &vkGPU->physicalDeviceProperties);
167	vkGetPhysicalDeviceMemoryProperties(vkGPU->physicalDevice, &vkGPU->physicalDeviceMemoryProperties);
168
169	glslang_initialize_process();//compiler can be initialized before VkFFT
170#elif(VKFFT_BACKEND==1)
171	CUresult res = CUDA_SUCCESS;
172	cudaError_t res2 = cudaSuccess;
173	res = cuInit(0);
174	if (res != CUDA_SUCCESS) return VKFFT_ERROR_FAILED_TO_INITIALIZE;
175	res2 = cudaSetDevice((int)vkGPU->device_id);
176	if (res2 != cudaSuccess) return VKFFT_ERROR_FAILED_TO_SET_DEVICE_ID;
177	res = cuDeviceGet(&vkGPU->device, (int)vkGPU->device_id);
178	if (res != CUDA_SUCCESS) return VKFFT_ERROR_FAILED_TO_GET_DEVICE;
179	res = cuCtxCreate(&vkGPU->context, 0, (int)vkGPU->device);
180	if (res != CUDA_SUCCESS) return VKFFT_ERROR_FAILED_TO_CREATE_CONTEXT;
181#elif(VKFFT_BACKEND==2)
182	hipError_t res = hipSuccess;
183	res = hipInit(0);
184	if (res != hipSuccess) return VKFFT_ERROR_FAILED_TO_INITIALIZE;
185	res = hipSetDevice((int)vkGPU->device_id);
186	if (res != hipSuccess) return VKFFT_ERROR_FAILED_TO_SET_DEVICE_ID;
187	res = hipDeviceGet(&vkGPU->device, (int)vkGPU->device_id);
188	if (res != hipSuccess) return VKFFT_ERROR_FAILED_TO_GET_DEVICE;
189	res = hipCtxCreate(&vkGPU->context, 0, (int)vkGPU->device);
190	if (res != hipSuccess) return VKFFT_ERROR_FAILED_TO_CREATE_CONTEXT;
191#elif(VKFFT_BACKEND==3)
192	cl_int res = CL_SUCCESS;
193	cl_uint numPlatforms;
194	res = clGetPlatformIDs(0, 0, &numPlatforms);
195	if (res != CL_SUCCESS) return VKFFT_ERROR_FAILED_TO_INITIALIZE;
196	cl_platform_id* platforms = (cl_platform_id*)malloc(sizeof(cl_platform_id) * numPlatforms);
197	if (!platforms) return VKFFT_ERROR_MALLOC_FAILED;
198	res = clGetPlatformIDs(numPlatforms, platforms, 0);
199	if (res != CL_SUCCESS) return VKFFT_ERROR_FAILED_TO_INITIALIZE;
200	uint64_t k = 0;
201	for (uint64_t j = 0; j < numPlatforms; j++) {
202		cl_uint numDevices;
203		res = clGetDeviceIDs(platforms[j], CL_DEVICE_TYPE_ALL, 0, 0, &numDevices);
204		cl_device_id* deviceList = (cl_device_id*)malloc(sizeof(cl_device_id) * numDevices);
205		if (!deviceList) return VKFFT_ERROR_MALLOC_FAILED;
206		res = clGetDeviceIDs(platforms[j], CL_DEVICE_TYPE_ALL, numDevices, deviceList, 0);
207		if (res != CL_SUCCESS) return VKFFT_ERROR_FAILED_TO_GET_DEVICE;
208		for (uint64_t i = 0; i < numDevices; i++) {
209			if (k == vkGPU->device_id) {
210				vkGPU->platform = platforms[j];
211				vkGPU->device = deviceList[i];
212				vkGPU->context = clCreateContext(NULL, 1, &vkGPU->device, NULL, NULL, &res);
213				if (res != CL_SUCCESS) return VKFFT_ERROR_FAILED_TO_CREATE_CONTEXT;
214				cl_command_queue commandQueue = clCreateCommandQueue(vkGPU->context, vkGPU->device, 0, &res);
215				if (res != CL_SUCCESS) return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_QUEUE;
216				vkGPU->commandQueue = commandQueue;
217				i=numDevices;
218				j=numPlatforms;
219			}
220			else {
221				k++;
222			}
223		}
224		free(deviceList);
225	}
226	free(platforms);
227#elif(VKFFT_BACKEND==4)
228	ze_result_t res = ZE_RESULT_SUCCESS;
229	res = zeInit(0);
230	if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_INITIALIZE;
231	uint32_t numDrivers = 0;
232	res = zeDriverGet(&numDrivers, 0);
233	if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_INITIALIZE;
234	ze_driver_handle_t* drivers = (ze_driver_handle_t*)malloc(numDrivers * sizeof(ze_driver_handle_t));
235	if (!drivers) return VKFFT_ERROR_MALLOC_FAILED;
236	res = zeDriverGet(&numDrivers, drivers);
237	if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_INITIALIZE;
238	uint64_t k = 0;
239	for (uint64_t j = 0; j < numDrivers; j++) {
240		uint32_t numDevices = 0;
241		res = zeDeviceGet(drivers[j], &numDevices, nullptr);
242		if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_GET_DEVICE;
243		ze_device_handle_t* deviceList = (ze_device_handle_t*)malloc(numDevices * sizeof(ze_device_handle_t));
244		if (!deviceList) return VKFFT_ERROR_MALLOC_FAILED;
245		res = zeDeviceGet(drivers[j], &numDevices, deviceList);
246		if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_GET_DEVICE;
247		for (uint64_t i = 0; i < numDevices; i++) {
248			if (k == vkGPU->device_id) {
249				vkGPU->driver = drivers[j];
250				vkGPU->device = deviceList[i];
251				ze_context_desc_t contextDescription = {};
252				contextDescription.stype = ZE_STRUCTURE_TYPE_CONTEXT_DESC;
253				res = zeContextCreate(vkGPU->driver, &contextDescription, &vkGPU->context);
254				if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_CREATE_CONTEXT;
255
256				uint32_t queueGroupCount = 0;
257				res = zeDeviceGetCommandQueueGroupProperties(vkGPU->device, &queueGroupCount, 0);
258				if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_QUEUE;
259
260				ze_command_queue_group_properties_t* cmdqueueGroupProperties = (ze_command_queue_group_properties_t*)malloc(queueGroupCount * sizeof(ze_command_queue_group_properties_t));
261				if (!cmdqueueGroupProperties) return VKFFT_ERROR_MALLOC_FAILED;
262				res = zeDeviceGetCommandQueueGroupProperties(vkGPU->device, &queueGroupCount, cmdqueueGroupProperties);
263				if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_QUEUE;
264
265				uint32_t commandQueueID = -1;
266				for (uint32_t i = 0; i < queueGroupCount; ++i) {
267					if ((cmdqueueGroupProperties[i].flags & ZE_COMMAND_QUEUE_GROUP_PROPERTY_FLAG_COMPUTE) && (cmdqueueGroupProperties[i].flags & ZE_COMMAND_QUEUE_GROUP_PROPERTY_FLAG_COPY)) {
268						commandQueueID = i;
269						break;
270					}
271				}
272				if (commandQueueID == -1) return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_QUEUE;
273				vkGPU->commandQueueID = commandQueueID;
274				ze_command_queue_desc_t commandQueueDescription = {};
275				commandQueueDescription.stype = ZE_STRUCTURE_TYPE_COMMAND_QUEUE_DESC;
276				commandQueueDescription.ordinal = commandQueueID;
277				commandQueueDescription.priority = ZE_COMMAND_QUEUE_PRIORITY_NORMAL;
278				commandQueueDescription.mode = ZE_COMMAND_QUEUE_MODE_DEFAULT;
279				res = zeCommandQueueCreate(vkGPU->context, vkGPU->device, &commandQueueDescription, &vkGPU->commandQueue);
280				if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_QUEUE;
281				free(cmdqueueGroupProperties);
282				i=numDevices;
283				j=numDrivers;
284			}
285			else {
286				k++;
287			}
288		}
289
290		free(deviceList);
291	}
292	free(drivers);
293#elif(VKFFT_BACKEND==5)
294    NS::Array* devices = MTL::CopyAllDevices();
295    MTL::Device* device = (MTL::Device*)devices->object(vkGPU->device_id);
296    vkGPU->device = device;
297    MTL::CommandQueue* queue = device->newCommandQueue();
298    vkGPU->queue = queue;
299#endif
300
301	uint64_t isCompilerInitialized = 1;
302
303    switch (sample_id) {
304    case 0:
305    {
306        resFFT = sample_0_benchmark_VkFFT_single(vkGPU, file_output, output, isCompilerInitialized);
307        break;
308    }
309    case 1:
310    {
311        resFFT = sample_1_benchmark_VkFFT_double(vkGPU, file_output, output, isCompilerInitialized);
312        break;
313    }
314	case 2:
315    {
316        resFFT = sample_2_benchmark_VkFFT_half(vkGPU, file_output, output, isCompilerInitialized);
317        break;
318    }
319    case 3:
320    {
321        resFFT = sample_3_benchmark_VkFFT_single_3d(vkGPU, file_output, output, isCompilerInitialized);
322        break;
323    }
324    case 4:
325    {
326        resFFT = sample_4_benchmark_VkFFT_single_3d_zeropadding(vkGPU, file_output, output, isCompilerInitialized);
327        break;
328    }
329    case 5:
330    {
331        resFFT = sample_5_benchmark_VkFFT_single_disableReorderFourStep(vkGPU, file_output, output, isCompilerInitialized);
332        break;
333    }
334    case 6:
335    {
336        resFFT = sample_6_benchmark_VkFFT_single_r2c(vkGPU, file_output, output, isCompilerInitialized);
337        break;
338    }
339    case 7:
340    {
341        resFFT = sample_7_benchmark_VkFFT_single_Bluestein(vkGPU, file_output, output, isCompilerInitialized);
342        break;
343    }
344    case 8:
345    {
346        resFFT = sample_8_benchmark_VkFFT_double_Bluestein(vkGPU, file_output, output, isCompilerInitialized);
347        break;
348    }
349#ifdef VKFFT_USE_DOUBLEDOUBLE_FP128
350	case 9:
351	{
352		resFFT = sample_9_benchmark_VkFFT_quadDoubleDouble(vkGPU, file_output, output, isCompilerInitialized);
353		break;
354	}
355#endif
356#if(VKFFT_BACKEND==0)
357    case 10:
358    {
359        resFFT = sample_10_benchmark_VkFFT_single_multipleBuffers(vkGPU, file_output, output, isCompilerInitialized);
360        break;
361    }
362#endif
363#ifdef USE_FFTW
364    case 11:
365    {
366        resFFT = sample_11_precision_VkFFT_single(vkGPU, file_output, output, isCompilerInitialized);
367        break;
368    }
369    case 12:
370    {
371        resFFT = sample_12_precision_VkFFT_double(vkGPU, file_output, output, isCompilerInitialized);
372        break;
373    }
374	case 13:
375    {
376        resFFT = sample_13_precision_VkFFT_half(vkGPU, file_output, output, isCompilerInitialized);
377        break;
378    }
379    case 14:
380    {
381        resFFT = sample_14_precision_VkFFT_single_nonPow2(vkGPU, file_output, output, isCompilerInitialized);
382        break;
383    }
384    case 15:
385    {
386        resFFT = sample_15_precision_VkFFT_single_r2c(vkGPU, file_output, output, isCompilerInitialized);
387        break;
388    }
389    case 16:
390    {
391        resFFT = sample_16_precision_VkFFT_single_dct(vkGPU, file_output, output, isCompilerInitialized);
392        break;
393    }
394    case 17:
395    {
396        resFFT = sample_17_precision_VkFFT_double_dct(vkGPU, file_output, output, isCompilerInitialized);
397        break;
398    }
399    case 18:
400    {
401        resFFT = sample_18_precision_VkFFT_double_nonPow2(vkGPU, file_output, output, isCompilerInitialized);
402        break;
403    }
404#ifdef VKFFT_USE_DOUBLEDOUBLE_FP128
405	case 19:
406    {
407        resFFT = sample_19_precision_VkFFT_quadDoubleDouble_nonPow2(vkGPU, file_output, output, isCompilerInitialized);
408        break;
409    }
410#endif
411#endif
412    case 50:
413    {
414        resFFT = sample_50_convolution_VkFFT_single_1d_matrix(vkGPU, file_output, output, isCompilerInitialized);
415        break;
416    }
417    case 51:
418    {
419        resFFT = sample_51_convolution_VkFFT_single_3d_matrix_zeropadding_r2c(vkGPU, file_output, output, isCompilerInitialized);
420        break;
421    }
422    case 52:
423    {
424        resFFT = sample_52_convolution_VkFFT_single_2d_batched_r2c(vkGPU, file_output, output, isCompilerInitialized);
425        break;
426    }
427    case 110:
428    {
429        resFFT = sample_100_benchmark_VkFFT_single_nd_dct(vkGPU, file_output, output, isCompilerInitialized, 1);
430        break;
431    }
432    case 120:
433    {
434        resFFT = sample_100_benchmark_VkFFT_single_nd_dct(vkGPU, file_output, output, isCompilerInitialized, 2);
435        break;
436    }
437    case 130:
438    {
439        resFFT = sample_100_benchmark_VkFFT_single_nd_dct(vkGPU, file_output, output, isCompilerInitialized, 3);
440        break;
441    }
442    case 140:
443    {
444        resFFT = sample_100_benchmark_VkFFT_single_nd_dct(vkGPU, file_output, output, isCompilerInitialized, 4);
445        break;
446    }
447    case 111:
448    {
449        resFFT = sample_101_benchmark_VkFFT_double_nd_dct(vkGPU, file_output, output, isCompilerInitialized, 1);
450        break;
451    }
452    case 121:
453    {
454        resFFT = sample_101_benchmark_VkFFT_double_nd_dct(vkGPU, file_output, output, isCompilerInitialized, 2);
455        break;
456    }
457    case 131:
458    {
459        resFFT = sample_101_benchmark_VkFFT_double_nd_dct(vkGPU, file_output, output, isCompilerInitialized, 3);
460        break;
461    }
462    case 141:
463    {
464        resFFT = sample_101_benchmark_VkFFT_double_nd_dct(vkGPU, file_output, output, isCompilerInitialized, 4);
465        break;
466    }
467    case 200: case 201: case 202:
468    {
469        resFFT = user_benchmark_VkFFT(vkGPU, file_output, output, isCompilerInitialized, userParams);
470        break;
471    }
472#ifdef VKFFT_USE_DOUBLEDOUBLE_FP128
473	case 203:
474    {
475        resFFT = user_benchmark_VkFFT(vkGPU, file_output, output, isCompilerInitialized, userParams);
476        break;
477    }
478#endif
479    case 1000:
480    {
481        resFFT = sample_1000_benchmark_VkFFT_single_2_4096(vkGPU, file_output, output, isCompilerInitialized);
482        break;
483    }
484    case 1001:
485    {
486        resFFT = sample_1001_benchmark_VkFFT_double_2_4096(vkGPU, file_output, output, isCompilerInitialized);
487        break;
488    }
489	case 1002:
490	{
491		resFFT = sample_1002_benchmark_VkFFT_half_2_4096(vkGPU, file_output, output, isCompilerInitialized);
492		break;
493	}
494    case 1003:
495    {
496        resFFT = sample_1003_benchmark_VkFFT_single_3d_2_512(vkGPU, file_output, output, isCompilerInitialized);
497        break;
498    }
499#ifdef VKFFT_USE_DOUBLEDOUBLE_FP128	
500	case 1004:
501	{
502		resFFT = sample_1004_benchmark_VkFFT_quadDoubleDouble_2_4096(vkGPU, file_output, output, isCompilerInitialized);
503		break;
504	}
505#endif
506    }
507#if(VKFFT_BACKEND==0)
508	vkDestroyFence(vkGPU->device, vkGPU->fence, NULL);
509	vkDestroyCommandPool(vkGPU->device, vkGPU->commandPool, NULL);
510	vkDestroyDevice(vkGPU->device, NULL);
511	DestroyDebugUtilsMessengerEXT(vkGPU, NULL);
512	vkDestroyInstance(vkGPU->instance, NULL);
513	glslang_finalize_process();//destroy compiler after use
514#elif(VKFFT_BACKEND==1)
515	res = cuCtxDestroy(vkGPU->context);
516#elif(VKFFT_BACKEND==2)
517	res = hipCtxDestroy(vkGPU->context);
518#elif(VKFFT_BACKEND==3)
519	res = clReleaseCommandQueue(vkGPU->commandQueue);
520	if (res != CL_SUCCESS) return VKFFT_ERROR_FAILED_TO_RELEASE_COMMAND_QUEUE;
521	clReleaseContext(vkGPU->context);
522#elif(VKFFT_BACKEND==4)
523	res = zeCommandQueueDestroy(vkGPU->commandQueue);
524	if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_RELEASE_COMMAND_QUEUE;
525	res = zeContextDestroy(vkGPU->context);
526#elif(VKFFT_BACKEND==5)
527    vkGPU->queue->release();
528    vkGPU->device->release();
529    devices->release();
530#endif
531
532	return resFFT;
533}
534
535bool findFlag(char** start, char** end, const std::string& flag) {
536	return (std::find(start, end, flag) != end);
537}
538char* getFlagValue(char** start, char** end, const std::string& flag)
539{
540	char** value = std::find(start, end, flag);
541	value++;
542	if (value != end)
543	{
544		return *value;
545	}
546	return 0;
547}
548int main(int argc, char* argv[])
549{
550	VkGPU vkGPU = {};
551#if(VKFFT_BACKEND==0)
552	vkGPU.enableValidationLayers = 0;
553#endif
554	bool file_output = false;
555	FILE* output = NULL;
556	int sscanf_res = 0;
557	if (findFlag(argv, argv + argc, "-h"))
558	{
559		//print help
560		int version = VkFFTGetVersion();
561		int version_decomposed[3];
562		version_decomposed[0] = version / 10000;
563		version_decomposed[1] = (version - version_decomposed[0] * 10000) / 100;
564		version_decomposed[2] = (version - version_decomposed[0] * 10000 - version_decomposed[1] * 100);
565		printf("VkFFT v%d.%d.%d (05-02-2024). Author: Tolmachev Dmitrii\n", version_decomposed[0], version_decomposed[1], version_decomposed[2]);
566#if (VKFFT_BACKEND==0)
567		printf("Vulkan backend\n");
568#elif (VKFFT_BACKEND==1)
569		printf("CUDA backend\n");
570#elif (VKFFT_BACKEND==2)
571		printf("HIP backend\n");
572#elif (VKFFT_BACKEND==3)
573		printf("OpenCL backend\n");
574#elif (VKFFT_BACKEND==4)
575		printf("Level Zero backend\n");
576#elif (VKFFT_BACKEND==5)
577        printf("Metal backend\n");
578#endif
579		printf("	-h: print help\n");
580		printf("	-devices: print the list of available device ids, used as -d argument\n");
581		printf("	-d X: select device (default 0)\n");
582		printf("	-o NAME: specify output file path\n");
583		printf("	-vkfft X: launch VkFFT sample X:\n");
584		printf("		0 - FFT + iFFT C2C benchmark 1D batched in single precision\n");
585		printf("		1 - FFT + iFFT C2C benchmark 1D batched in double precision LUT\n");
586		printf("		2 - FFT + iFFT C2C benchmark 1D batched in half precision\n");	
587		printf("		3 - FFT + iFFT C2C multidimensional benchmark in single precision\n");
588		printf("		4 - FFT + iFFT C2C multidimensional benchmark in single precision, native zeropadding\n");
589		printf("		5 - FFT + iFFT C2C benchmark 1D batched in single precision, no reshuffling\n");
590		printf("		6 - FFT + iFFT R2C / C2R benchmark\n");
591		printf("		7 - FFT + iFFT C2C Bluestein benchmark in single precision\n");
592		printf("		8 - FFT + iFFT C2C Bluestein benchmark in double precision\n");
593#ifdef VKFFT_USE_DOUBLEDOUBLE_FP128
594		printf("		9 - FFT + iFFT C2C benchmark 1D batched in double-double emulation of quad precision LUT\n");
595#endif
596#if (VKFFT_BACKEND==0)
597		printf("		10 - multiple buffer(4 by default) split version of benchmark 0\n");
598#endif
599#ifdef USE_FFTW
600#ifdef USE_cuFFT
601		printf("		11 - VkFFT / cuFFT / FFTW C2C precision test in single precision\n");
602		printf("		12 - VkFFT / cuFFT / FFTW C2C precision test in double precision\n");
603		printf("		13 - VkFFT / cuFFT / FFTW C2C precision test in half precision\n");
604		printf("		14 - VkFFT / FFTW C2C radix 3 / 5 / 7 / 11 / 13 / Bluestein precision test in single precision\n");
605		printf("		15 - VkFFT / cuFFT / FFTW R2C+C2R precision test in single precision\n");
606		printf("		16 - VkFFT / FFTW R2R DCT-I, II, III and IV precision test in single precision\n");
607		printf("		17 - VkFFT / FFTW R2R DCT-I, II, III and IV precision test in double precision\n");
608		printf("		18 - VkFFT / FFTW C2C radix 3 / 5 / 7 / 11 / 13 / Bluestein precision test in double precision\n");
609#ifdef VKFFT_USE_DOUBLEDOUBLE_FP128
610		printf("		19 - VkFFT / FFTW C2C precision test in double-double emulation of quad precision\n");
611#endif
612#elif USE_rocFFT
613		printf("		11 - VkFFT / rocFFT / FFTW C2C precision test in single precision\n");
614		printf("		12 - VkFFT / rocFFT / FFTW C2C precision test in double precision\n");
615		printf("		13 - VkFFT / FFTW C2C precision test in half precision\n");
616		printf("		14 - VkFFT / FFTW C2C radix 3 / 5 / 7 / 11 / 13 / Bluestein precision test in single precision\n");
617		printf("		15 - VkFFT / rocFFT / FFTW R2C+C2R precision test in single precision\n");
618		printf("		16 - VkFFT / FFTW R2R DCT-I, II, III and IV precision test in single precision\n");
619		printf("		17 - VkFFT / FFTW R2R DCT-I, II, III and IV precision test in double precision\n");
620		printf("		18 - VkFFT / FFTW C2C radix 3 / 5 / 7 / 11 / 13 / Bluestein precision test in double precision\n");
621#ifdef VKFFT_USE_DOUBLEDOUBLE_FP128
622		printf("		19 - VkFFT / FFTW C2C precision test in double-double emulation of quad precision\n");
623#endif
624#else
625		printf("		11 - VkFFT / FFTW C2C precision test in single precision\n");
626		printf("		12 - VkFFT / FFTW C2C precision test in double precision\n");
627		printf("		13 - VkFFT / FFTW C2C precision test in half precision\n");
628		printf("		14 - VkFFT / FFTW C2C radix 3 / 5 / 7 / 11 / 13 / Bluestein precision test in single precision\n");
629		printf("		15 - VkFFT / FFTW R2C+C2R precision test in single precision\n");
630		printf("		16 - VkFFT / FFTW R2R DCT-I, II, III and IV precision test in single precision\n");
631		printf("		17 - VkFFT / FFTW R2R DCT-I, II, III and IV precision test in double precision\n");
632		printf("		18 - VkFFT / FFTW C2C radix 3 / 5 / 7 / 11 / 13 / Bluestein precision test in double precision\n");
633#ifdef VKFFT_USE_DOUBLEDOUBLE_FP128
634		printf("		19 - VkFFT / FFTW C2C precision test in double-double emulation of quad precision\n");
635#endif
636#endif
637#endif
638		printf("		50 - convolution example with identity kernel\n");
639		printf("		51 - zeropadding convolution example with identity kernel\n");
640		printf("		52 - batched convolution example with identity kernel\n");
641		printf("		110 - VkFFT FFT + iFFT R2R DCT-1 multidimensional benchmark in single precision\n");
642		printf("		111 - VkFFT FFT + iFFT R2R DCT-1 multidimensional benchmark in double precision\n");
643		printf("		120 - VkFFT FFT + iFFT R2R DCT-2 multidimensional benchmark in single precision\n");
644		printf("		121 - VkFFT FFT + iFFT R2R DCT-2 multidimensional benchmark in double precision\n");
645		printf("		130 - VkFFT FFT + iFFT R2R DCT-3 multidimensional benchmark in single precision\n");
646		printf("		131 - VkFFT FFT + iFFT R2R DCT-3 multidimensional benchmark in double precision\n");
647		printf("		140 - VkFFT FFT + iFFT R2R DCT-4 multidimensional benchmark in single precision\n");
648		printf("		141 - VkFFT FFT + iFFT R2R DCT-4 multidimensional benchmark in double precision\n");
649
650		printf("		1000 - FFT + iFFT C2C benchmark 1D batched in single precision: all supported systems from 2 to 4096\n");
651		printf("		1001 - FFT + iFFT C2C benchmark 1D batched in double precision: all supported systems from 2 to 4096\n");
652		printf("		1002 - FFT + iFFT C2C benchmark 1D batched in half precision: all supported systems from 2 to 4096\n");
653		printf("		1003 - FFT + iFFT C2C multidimensional benchmark in single precision: all supported cubes from 2 to 512\n");
654#ifdef VKFFT_USE_DOUBLEDOUBLE_FP128
655		printf("		1004 - FFT + iFFT C2C benchmark 1D batched in double-double emulation of quad precision: all supported systems from 2 to 4096\n");
656#endif
657		printf("	-benchmark_vkfft: run VkFFT benchmark on a user-defined system:\n\
658		-X uint, -Y uint, -Z uint - FFT dimensions (default Y and Z are 1)\n");
659		printf("\
660		-P uint - precision (0 - single, 1 - double, 2 - half, 3 - double-double) (default 0)\n");
661		printf("\
662		-B uint - number of batched systems (default 1)\n\
663		-N uint - number of consecutive FFT+iFFT iterations (default 1)\n\
664		-R2C uint - use R2C (0 - off, 1 - on) (default 0)\n\
665		-DCT uint - perform DCT (0 - off, else type: 1, 2, 3 or 4) (default 0)\n\
666		-save - save generated binaries\n\
667		-load - load previously generated binaries\n");
668#ifdef USE_cuFFT
669		printf("	-cufft X: launch cuFFT sample X:\n");
670		printf("		0 - FFT + iFFT C2C benchmark 1D batched in single precision\n");
671		printf("		1 - FFT + iFFT C2C benchmark 1D batched in double precision LUT\n");
672		printf("		2 - FFT + iFFT C2C benchmark 1D batched in half precision\n");
673		printf("		3 - FFT + iFFT C2C multidimensional benchmark in single precision\n");
674		printf("		6 - FFT + iFFT R2C / C2R benchmark\n");
675		printf("		7 - FFT + iFFT C2C big prime benchmark in single precision (similar to VkFFT Bluestein)\n");
676		printf("		8 - FFT + iFFT C2C big prime benchmark in double precision (similar to VkFFT Bluestein)\n");
677		printf("		1000 - FFT + iFFT C2C benchmark 1D batched in single precision: all supported systems from 2 to 4096\n");
678		printf("		1001 - FFT + iFFT C2C benchmark 1D batched in double precision: all supported systems from 2 to 4096\n");
679		printf("		1003 - FFT + iFFT C2C multidimensional benchmark in single precision: all supported cubes from 2 to 512\n");
680		printf("	-test: (or no -vkfft and -cufft keys) run vkfft benchmarks 0-6 and cufft benchmarks 0-6\n");
681		printf("	-benchmark_cufft: run cuFFT benchmark on a user-defined system:\n\
682		-X uint, -Y uint, -Z uint - FFT dimensions (default Y and Z are 1)\n\
683		-P uint - precision (0 - single, 1 - double) (default 0)\n\
684		-B uint - number of batched systems (default 1)\n\
685		-N uint - number of consecutive FFT+iFFT iterations (default 1)\n\
686		-R2C uint - use R2C (0 - off, 1 - on) (default 0)\n");
687#elif USE_rocFFT
688		printf("	-rocfft X: launch rocFFT sample X:\n");
689		printf("		0 - FFT + iFFT C2C benchmark 1D batched in single precision\n");
690		printf("		1 - FFT + iFFT C2C benchmark 1D batched in double precision LUT\n");
691		printf("		3 - FFT + iFFT C2C multidimensional benchmark in single precision\n");
692		printf("		6 - FFT + iFFT R2C / C2R benchmark\n");
693		printf("		7 - FFT + iFFT C2C big prime benchmark in single precision (similar to VkFFT Bluestein)\n");
694		printf("		8 - FFT + iFFT C2C big prime benchmark in double precision (similar to VkFFT Bluestein)\n");
695		printf("		1000 - FFT + iFFT C2C benchmark 1D batched in single precision: all supported systems from 2 to 4096\n");
696		printf("		1001 - FFT + iFFT C2C benchmark 1D batched in double precision: all supported systems from 2 to 4096\n");
697		printf("		1003 - FFT + iFFT C2C multidimensional benchmark in single precision: all supported cubes from 2 to 512\n");
698		printf("	-test: (or no -vkfft and -rocfft keys) run vkfft benchmarks 0-6 and rocfft benchmarks 0-6\n");
699		printf("	-benchmark_rocfft: run rocFFT benchmark on a user-defined system:\n\
700		-X uint, -Y uint, -Z uint - FFT dimensions (default Y and Z are 1)\n\
701		-P uint - precision (0 - single, 1 - double) (default 0)\n\
702		-B uint - number of batched systems (default 1)\n\
703		-N uint - number of consecutive FFT+iFFT iterations (default 1)\n\
704		-R2C uint - use R2C (0 - off, 1 - on) (default 0)\n");
705#else
706		printf("	-test: run vkfft benchmarks 0-6\n");
707		printf("	-cufft command is disabled\n");
708		printf("	-rocfft command is disabled\n");
709#endif
710		return 0;
711	}
712	if (findFlag(argv, argv + argc, "-devices"))
713	{
714		//print device list
715		VkFFTResult resFFT = devices_list();
716		return resFFT;
717	}
718	if (findFlag(argv, argv + argc, "-d"))
719	{
720		//select device_id
721		char* value = getFlagValue(argv, argv + argc, "-d");
722		if (value != 0) {
723			sscanf_res = sscanf(value, "%" PRIu64 "", &vkGPU.device_id);
724			if (sscanf_res <= 0) {
725				printf("sscanf failed\n");
726				return 1;
727			}
728		}
729		else {
730			printf("No device is selected with -d flag\n");
731			return 1;
732		}
733	}
734	if (findFlag(argv, argv + argc, "-o"))
735	{
736		//specify output file
737		char* value = getFlagValue(argv, argv + argc, "-o");
738		if (value != 0) {
739			file_output = true;
740			output = fopen(value, "a");
741		}
742		else {
743			printf("No output file is selected with -o flag\n");
744			return 1;
745		}
746	}
747	if (findFlag(argv, argv + argc, "-benchmark_vkfft") || findFlag(argv, argv + argc, "-benchmark_cufft") || findFlag(argv, argv + argc, "-benchmark_rocfft"))
748	{
749		//select sample_id
750		VkFFTUserSystemParameters userParams = {};
751		userParams.X = 1;
752		userParams.Y = 1;
753		userParams.Z = 1;
754		userParams.P = 0;
755		userParams.B = 1;
756		userParams.N = 1;
757		userParams.R2C = 0;
758		userParams.DCT = 0;
759		if (findFlag(argv, argv + argc, "-X"))
760		{
761			char* value = getFlagValue(argv, argv + argc, "-X");
762			if (value != 0) {
763				sscanf_res = sscanf(value, "%" PRIu64 "", &userParams.X);
764				if (sscanf_res <= 0) {
765					printf("sscanf failed\n");
766					return 1;
767				}
768			}
769			else {
770				printf("No dimension is selected with -X flag\n");
771				return 1;
772			}
773		}
774		else {
775			printf("No -X flag is selected\n");
776			return 1;
777		}
778		if (findFlag(argv, argv + argc, "-Y"))
779		{
780			char* value = getFlagValue(argv, argv + argc, "-Y");
781			if (value != 0) {
782				sscanf_res = sscanf(value, "%" PRIu64 "", &userParams.Y);
783				if (sscanf_res <= 0) {
784					printf("sscanf failed\n");
785					return 1;
786				}
787			}
788			else {
789				printf("No dimension is selected with -Y flag\n");
790				return 1;
791			}
792		}
793		if (findFlag(argv, argv + argc, "-Z"))
794		{
795			char* value = getFlagValue(argv, argv + argc, "-Z");
796			if (value != 0) {
797				sscanf_res = sscanf(value, "%" PRIu64 "", &userParams.Z);
798				if (sscanf_res <= 0) {
799					printf("sscanf failed\n");
800					return 1;
801				}
802			}
803			else {
804				printf("No dimension is selected with -Z flag\n");
805				return 1;
806			}
807		}
808		if (findFlag(argv, argv + argc, "-P"))
809		{
810			char* value = getFlagValue(argv, argv + argc, "-P");
811			if (value != 0) {
812				sscanf_res = sscanf(value, "%" PRIu64 "", &userParams.P);
813				if (sscanf_res <= 0) {
814					printf("sscanf failed\n");
815					return 1;
816				}
817			}
818			else {
819				printf("No precision is selected with -P flag\n");
820				return 1;
821			}
822		}
823		if (findFlag(argv, argv + argc, "-B"))
824		{
825			char* value = getFlagValue(argv, argv + argc, "-B");
826			if (value != 0) {
827				sscanf_res = sscanf(value, "%" PRIu64 "", &userParams.B);
828				if (sscanf_res <= 0) {
829					printf("sscanf failed\n");
830					return 1;
831				}
832			}
833			else {
834				printf("No batch is selected with -B flag\n");
835				return 1;
836			}
837		}
838		if (findFlag(argv, argv + argc, "-N"))
839		{
840			char* value = getFlagValue(argv, argv + argc, "-N");
841			if (value != 0) {
842				sscanf_res = sscanf(value, "%" PRIu64 "", &userParams.N);
843				if (sscanf_res <= 0) {
844					printf("sscanf failed\n");
845					return 1;
846				}
847			}
848			else {
849				printf("No number of iterations is selected with -N flag\n");
850				return 1;
851			}
852		}
853		if (findFlag(argv, argv + argc, "-R2C"))
854		{
855			char* value = getFlagValue(argv, argv + argc, "-R2C");
856			if (value != 0) {
857				sscanf_res = sscanf(value, "%" PRIu64 "", &userParams.R2C);
858				if (sscanf_res <= 0) {
859					printf("sscanf failed\n");
860					return 1;
861				}
862			}
863			else {
864				printf("No R2C parameter is selected with -R2C flag\n");
865				return 1;
866			}
867		}
868		if (findFlag(argv, argv + argc, "-DCT"))
869		{
870			char* value = getFlagValue(argv, argv + argc, "-DCT");
871			if (value != 0) {
872				sscanf_res = sscanf(value, "%" PRIu64 "", &userParams.DCT);
873				if (sscanf_res <= 0) {
874					printf("sscanf failed\n");
875					return 1;
876				}
877			}
878			else {
879				printf("No DCT parameter is selected with -DCT flag\n");
880				return 1;
881			}
882		}
883		if (findFlag(argv, argv + argc, "-save"))
884		{
885			userParams.saveApplicationToString = 1;
886		}
887		if (findFlag(argv, argv + argc, "-load"))
888		{
889			userParams.loadApplicationFromString = 1;
890		}
891		if (findFlag(argv, argv + argc, "-benchmark_vkfft")) {
892			VkFFTResult resFFT = launchVkFFT(&vkGPU, 200 + userParams.P, file_output, output, &userParams);
893			if (resFFT != VKFFT_SUCCESS) return resFFT;
894		}
895		else {
896#ifdef USE_cuFFT
897			if (findFlag(argv, argv + argc, "-benchmark_cufft")) {
898				user_benchmark_cuFFT(file_output, output, (cuFFTUserSystemParameters*)(&userParams), (int)vkGPU.device_id);
899			}
900			return 0;
901#elif USE_rocFFT
902			if (findFlag(argv, argv + argc, "-benchmark_rocfft")) {
903				user_benchmark_rocFFT(file_output, output, (rocFFTUserSystemParameters*)(&userParams), (int)vkGPU.device_id);
904			}
905			return 0;
906#endif
907			return 1;
908		}
909		return 0;
910	}
911
912	if (findFlag(argv, argv + argc, "-vkfft"))
913	{
914		//select sample_id
915		char* value = getFlagValue(argv, argv + argc, "-vkfft");
916		if (value != 0) {
917			uint64_t sample_id = 0;
918			sscanf_res = sscanf(value, "%" PRIu64 "", &sample_id);
919			if (sscanf_res <= 0) {
920				printf("sscanf failed\n");
921				return 1;
922			}
923			VkFFTResult resFFT = launchVkFFT(&vkGPU, sample_id, file_output, output, 0);
924			if (resFFT != VKFFT_SUCCESS) return resFFT;
925		}
926		else {
927			printf("No sample is selected with -vkfft flag\n");
928			return 1;
929		}
930	}
931#ifdef USE_cuFFT
932	if (findFlag(argv, argv + argc, "-cufft"))
933	{
934		//select sample_id
935		char* value = getFlagValue(argv, argv + argc, "-cufft");
936		if (value != 0) {
937			uint64_t sample_id = 0;
938			sscanf_res = sscanf(value, "%" PRIu64 "", &sample_id);
939			if (sscanf_res <= 0) {
940				printf("sscanf failed\n");
941				return 1;
942			}
943			switch (sample_id) {
944			case 0:
945				sample_0_benchmark_cuFFT_single(file_output, output, (int)vkGPU.device_id);
946				break;
947			case 1:
948				sample_1_benchmark_cuFFT_double(file_output, output, (int)vkGPU.device_id);
949				break;
950			case 2:
951				sample_2_benchmark_cuFFT_half(file_output, output, (int)vkGPU.device_id);
952				break;
953			case 3:
954				sample_3_benchmark_cuFFT_single_3d(file_output, output, (int)vkGPU.device_id);
955				break;
956			case 6:
957				sample_6_benchmark_cuFFT_single_r2c(file_output, output, (int)vkGPU.device_id);
958				break;
959			case 7:
960				sample_7_benchmark_cuFFT_single_Bluestein(file_output, output, (int)vkGPU.device_id);
961				break;
962			case 8:
963				sample_8_benchmark_cuFFT_double_Bluestein(file_output, output, (int)vkGPU.device_id);
964				break;
965			case 1000:
966				sample_1000_benchmark_cuFFT_single_2_4096(file_output, output, (int)vkGPU.device_id);
967				break;
968			case 1001:
969				sample_1001_benchmark_cuFFT_double_2_4096(file_output, output, (int)vkGPU.device_id);
970				break;
971			case 1003:
972				sample_1003_benchmark_cuFFT_single_3d_2_512(file_output, output, (int)vkGPU.device_id);
973				break;
974			}
975		}
976		else {
977			printf("No cuFFT script is selected with -cufft flag\n");
978			return 1;
979		}
980	}
981#elif USE_rocFFT
982	if (findFlag(argv, argv + argc, "-rocfft"))
983	{
984		//select sample_id
985		char* value = getFlagValue(argv, argv + argc, "-rocfft");
986		if (value != 0) {
987			uint64_t sample_id = 0;
988			sscanf_res = sscanf(value, "%" PRIu64 "", &sample_id);
989			if (sscanf_res <= 0) {
990				printf("sscanf failed\n");
991				return 1;
992			}
993			switch (sample_id) {
994			case 0:
995				sample_0_benchmark_rocFFT_single(file_output, output, (int)vkGPU.device_id);
996				break;
997			case 1:
998				sample_1_benchmark_rocFFT_double(file_output, output, (int)vkGPU.device_id);
999				break;
1000			case 3:
1001				sample_3_benchmark_rocFFT_single_3d(file_output, output, (int)vkGPU.device_id);
1002				break;
1003			case 6:
1004				sample_6_benchmark_rocFFT_single_r2c(file_output, output, (int)vkGPU.device_id);
1005				break;
1006			case 7:
1007				sample_7_benchmark_rocFFT_single_Bluestein(file_output, output, (int)vkGPU.device_id);
1008				break;
1009			case 8:
1010				sample_8_benchmark_rocFFT_double_Bluestein(file_output, output, (int)vkGPU.device_id);
1011				break;
1012			case 1000:
1013				sample_1000_benchmark_rocFFT_single_2_4096(file_output, output, (int)vkGPU.device_id);
1014				break;
1015			case 1001:
1016				sample_1001_benchmark_rocFFT_double_2_4096(file_output, output, (int)vkGPU.device_id);
1017				break;
1018			case 1003:
1019				sample_1003_benchmark_rocFFT_single_3d_2_512(file_output, output, (int)vkGPU.device_id);
1020				break;
1021			}
1022		}
1023		else {
1024			printf("No rocFFT script is selected with -rocfft flag\n");
1025			return 1;
1026		}
1027	}
1028#endif
1029	if ((findFlag(argv, argv + argc, "-test")) || ((!findFlag(argv, argv + argc, "-cufft")) && (!findFlag(argv, argv + argc, "-rocfft")) && (!findFlag(argv, argv + argc, "-vkfft"))))
1030	{
1031		if (output == NULL) {
1032			file_output = true;
1033			output = fopen("result.txt", "a");
1034		}
1035		for (uint64_t i = 0; i < 9; i++) {
1036#if((VKFFT_BACKEND>0) || (VK_API_VERSION == 10))
1037			if (i == 2) i++;
1038#endif
1039			VkFFTResult resFFT = launchVkFFT(&vkGPU, i, file_output, output, 0);
1040			if (resFFT != VKFFT_SUCCESS) return resFFT;
1041		}
1042#ifdef USE_cuFFT
1043		sample_0_benchmark_cuFFT_single(file_output, output, (int)vkGPU.device_id);
1044		sample_1_benchmark_cuFFT_double(file_output, output, (int)vkGPU.device_id);
1045		sample_2_benchmark_cuFFT_half(file_output, output, (int)vkGPU.device_id);
1046		sample_3_benchmark_cuFFT_single_3d(file_output, output, (int)vkGPU.device_id);
1047		sample_6_benchmark_cuFFT_single_r2c(file_output, output, (int)vkGPU.device_id);
1048		sample_7_benchmark_cuFFT_single_Bluestein(file_output, output, (int)vkGPU.device_id);
1049		sample_8_benchmark_cuFFT_double_Bluestein(file_output, output, (int)vkGPU.device_id);
1050#elif USE_rocFFT
1051		sample_0_benchmark_rocFFT_single(file_output, output, (int)vkGPU.device_id);
1052		sample_1_benchmark_rocFFT_double(file_output, output, (int)vkGPU.device_id);
1053		sample_3_benchmark_rocFFT_single_3d(file_output, output, (int)vkGPU.device_id);
1054		sample_6_benchmark_rocFFT_single_r2c(file_output, output, (int)vkGPU.device_id);
1055		sample_7_benchmark_rocFFT_single_Bluestein(file_output, output, (int)vkGPU.device_id);
1056		sample_8_benchmark_rocFFT_double_Bluestein(file_output, output, (int)vkGPU.device_id);
1057#endif
1058	}
1059	return 0;
1060}