yum-mirror/VkFFT

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

Dmitrii TolmachevBugfixes -Fix for Metal and Level Zero push constants -Fix for Metal device/queue passing -Fix for Rader primes that use more threads than hw limit (https://github.com/vincefn/pyvkfft/issues/39#issuecomment-2378483882) -Fix for incorrect shared memory allocation in merged R2C case (https://github.com/vincefn/pyvkfft/issues/39#issuecomment-2378483882)79f7b7a

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