Example #1
0
File: main.cpp Project: rotty11/Pfc
/**
 * @brief Main principal
 * @param argc El número de argumentos del programa
 * @param argv Cadenas de argumentos del programa
 * @return Nada si es correcto o algún número negativo si es incorrecto
 */
int main( int argc, char** argv ) {

	if(argc != 2)
		return -1;

	// Medimos tiempo para el programa
	const double start_time = getCurrentTimestamp();

	FILE *kernels;
	char *source_str;
	size_t source_size, work_items;

	// OpenCL runtime configuration
	unsigned num_devices;
	cl_platform_id platform_ids[3];
	cl_uint ret_num_platforms;
	cl_device_id device_id;
	cl_context context = NULL;
	cl_command_queue command_queue;
	cl_program program = NULL;
	cl_int ret;
	cl_kernel kernelNUM;
	cl_event kernel_event, finish_event;
	cl_mem objPARTICULAS, objPESOS;

	// Abrimos el fichero que contiene el kernel
	fopen_s(&kernels, "numparticulasCPU.cl", "r");
	if (!kernels) {
		fprintf(stderr, "Fallo al cargar el kernel\n");
		exit(-1);
	}	
	source_str = (char *) malloc(0x100000);
	source_size = fread(source_str, 1, 0x100000, kernels);
	fclose(kernels);

	// Obtenemos los IDs de las plataformas disponibles
	if( clGetPlatformIDs(3, platform_ids, &ret_num_platforms) != CL_SUCCESS) {
		printf("No se puede obtener id de la plataforma");
		return -1;
	}

	// Intentamos obtener un dispositivo CPU soportado
	if( clGetDeviceIDs(platform_ids[1], CL_DEVICE_TYPE_CPU, 1, &device_id, &num_devices) != CL_SUCCESS) {
		printf("No se puede obtener id del dispositivo");
		return -1;
	}
	clGetDeviceInfo(device_id, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(cl_uint), &work_items, NULL);
 
	// Creación de un contexto OpenCL
	context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret);
 
	// Creación de una cola de comandos
	command_queue = clCreateCommandQueue(context, device_id, CL_QUEUE_PROFILING_ENABLE, &ret);

	// Creación de un programa kernel desde un fichero de código
	program = clCreateProgramWithSource(context, 1, (const char **)&source_str, (const size_t *)&source_size, &ret);
	ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);
	if (ret != CL_SUCCESS) {
		size_t len;
		char buffer[2048];
		printf("Error: ¡Fallo al construir el programa ejecutable!\n");
		clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &len);
		printf("%s", buffer);
		exit(-1);
	}

	// Creación del kernel OpenCL
	kernelNUM = clCreateKernel(program, "calc_num_particulas", &ret);

	// Creamos el buffer para las partículas y reservamos espacio ALINEADO para los datos
	size_t N = atoi(argv[1]);
	particle *particulas = (particle*) _aligned_malloc(N * sizeof(particle), 64);
	int *pesos = (int*) _aligned_malloc(N * sizeof(int), 64);
	objPARTICULAS = clCreateBuffer(context, CL_MEM_READ_ONLY, N * sizeof(particle), NULL, &ret);
	objPESOS = clCreateBuffer(context, CL_MEM_WRITE_ONLY, N * sizeof(int), NULL, &ret);
	float sum = 0.0f;
	const size_t global = 2;
	const size_t local_work_size = 1;

	// Inicializamos las partículas (Me interesan los pesos)
	srand(time(NULL));
	for(unsigned index = 0; index < N; ++index) {
		particulas[index].x = 0.0;
		particulas[index].y = 0.0;
		particulas[index].s = 0.0;
		particulas[index].xp = 0.0;
		particulas[index].yp = 0.0;
		particulas[index].sp = 0.0;
		particulas[index].x0 = 0.0;
		particulas[index].y0 = 0.0;
		particulas[index].width = 0;
		particulas[index].height = 0;
		particulas[index].w = (float) (rand() % 2000);
		sum+=particulas[index].w;
    }

	// Normalizamos los datos
	for(int i = 0; i < N; ++i)
		particulas[i].w /= sum;

	// Transferimos las partículas al dispositivo y los pesos
	cl_event write_event;
	ret = clEnqueueWriteBuffer(command_queue, objPARTICULAS, CL_FALSE, 0, N * sizeof(particle), particulas, 0, NULL, &write_event);

	// Establecemos los argumentos del kernel
	ret = clSetKernelArg(kernelNUM, 0, sizeof(cl_mem), &objPARTICULAS);
	ret = clSetKernelArg(kernelNUM, 1, sizeof(int), &N);
	ret = clSetKernelArg(kernelNUM, 2, sizeof(cl_mem), &objPESOS);

	// Ejecutamos el kernel. Un work-item por cada work-group o unidad de cómputo
	ret = clEnqueueNDRangeKernel(command_queue, kernelNUM, 1, NULL, &global, &local_work_size, 1, &write_event, &kernel_event);

	// Leemos los resultados
	ret = clEnqueueReadBuffer(command_queue, objPESOS, CL_FALSE, 0, N * sizeof(int), pesos, 1, &kernel_event, &finish_event);
	
	// Esperamos a que termine de leer los resultados
	clWaitForEvents(1, &finish_event);

	// Obtenemos el tiempo del kernel y de las transferencias CPU-RAM
	cl_ulong totalKernel = getStartEndTime(kernel_event);
	cl_ulong totalRam = getStartEndTime(write_event) + getStartEndTime(finish_event);

	const double end_time = getCurrentTimestamp();

	// Obtenemos el tiempo consumido por el programa, el kernel y las transferencias de memoria
	printf("\nTiempo total del programa: %0.3f ms\n", (end_time - start_time) * 1e3);
	printf("Tiempo total consumido por el kernel: %0.3f ms\n", double(totalKernel) * 1e-6);
	printf("Tiempo total consumido en transferencias CPU-RAM: %0.3f ms\n", double(totalRam) * 1e-6);

	// Liberamos todos los recursos usados (kernels y objetos OpenCL)
	clReleaseEvent(kernel_event);
	clReleaseEvent(finish_event);
	clReleaseEvent(write_event);
	clReleaseMemObject(objPARTICULAS);
	clReleaseMemObject(objPESOS);
	clReleaseKernel(kernelNUM);
	clReleaseCommandQueue(command_queue);
	clReleaseProgram(program);
	clReleaseContext(context);
}
Example #2
0
	//run waifu2x
	void run(std::vector<float> &input,
		std::vector<float> &weight,
		std::vector<float> &output,
		std::vector<double> &bias,
		int iter, const int kernelSize, int r, int c) {

		unsigned int ipp[7][1] = { { 1 },{ 32 },{ 32 },{ 64 },{ 64 },{ 128 },{ 128 } };
		unsigned int opp[7][1] = { { 32 },{ 32 },{ 64 },{ 64 },{ 128 },{ 128 },{ 1 } };

		const unsigned nInputPlanes = ipp[iter][1];
		const unsigned nOutputPlanes = opp[iter][1];

		cl_int status;

		status = clEnqueueWriteBuffer(queue, input_buf, CL_FALSE,
			0, r * c * nInputPlanes * sizeof(float), input.data(), 0, NULL, NULL);
		checkError(status, "Failed to transfer input");

		status = clEnqueueWriteBuffer(queue, weight_buf, CL_FALSE,
			0, kernelSize * nInputPlanes * nOutputPlanes * sizeof(float), weight.data(), 0, NULL, NULL);
		checkError(status, "Failed to transfer weight");

		status = clEnqueueWriteBuffer(queue, bias_buf, CL_FALSE,
			0, nOutputPlanes * sizeof(double), bias.data(), 0, NULL, NULL);
		checkError(status, "Failed to transfer bias");

		clFinish(queue);

		cl_event kernel_event;

		const double start_time = getCurrentTimestamp();

		unsigned argi = 0;

		status = clSetKernelArg(kernel, argi++, sizeof(cl_mem), &output_buf);
		checkError(status, "Failed to set argument %d", argi - 1);

		status = clSetKernelArg(kernel, argi++, sizeof(cl_mem), &input_buf);
		checkError(status, "Failed to set argument %d", argi - 1);

		status = clSetKernelArg(kernel, argi++, sizeof(cl_mem), &weight_buf);
		checkError(status, "Failed to set argument %d", argi - 1);

		status = clSetKernelArg(kernel, argi++, sizeof(cl_mem), &bias_buf);
		checkError(status, "Failed to set argument %d", argi - 1);

		status = clSetKernelArg(kernel, argi++, sizeof(nInputPlanes), &nInputPlanes);
		checkError(status, "Failed to set argument %d", argi - 1);

		status = clSetKernelArg(kernel, argi++, sizeof(nOutputPlanes), &nOutputPlanes);
		checkError(status, "Failed to set argument %d", argi - 1);

		status = clSetKernelArg(kernel, argi++, sizeof(r), &r);
		checkError(status, "Failed to set argument %d", argi - 1);

		status = clSetKernelArg(kernel, argi++, sizeof(c), &c);
		checkError(status, "Failed to set argument %d", argi - 1);

		const size_t* global_work_size = opp[iter];
		const size_t* local_work_size = ipp[iter];
		printf("Iteration %d\n", iter);

		status = clEnqueueNDRangeKernel(queue, kernel, 2, NULL,
			global_work_size, local_work_size, 0, NULL, &kernel_event);
		checkError(status, "Failed to launch kernel");

		status = clFinish(queue);
		checkError(status, "Failed to finish");

		const double end_time = getCurrentTimestamp();
		const double total_time = end_time - start_time;

		// Wall-clock time taken.
		printf("\nTime: %0.3f ms\n", total_time * 1e3);

		// Get kernel times using the OpenCL event profiling API.
		cl_ulong time_ns = getStartEndTime(kernel_event);
		printf("Kernel time: %0.3f ms\n", double(time_ns) * 1e-6);

		clReleaseEvent(kernel_event);

		status = clEnqueueReadBuffer(queue, output_buf, CL_TRUE,
			0, r - 1 * c - 1 * nOutputPlanes * sizeof(float), output.data(), 0, NULL, NULL);
		checkError(status, "Failed to read output matrix");

	}
Example #3
0
File: main.cpp Project: rotty11/Pfc
/**
 * @brief Main principal
 * @param argc El número de argumentos del programa
 * @param argv Cadenas de argumentos del programa
 * @return Nada si es correcto o algún número negativo si es incorrecto
 */
int main( int argc, char** argv ) {

	if(argc != 2)
		return -1;

	// Medimos tiempo para el programa
	const double start_time = getCurrentTimestamp();

	// Declaración de variables
	IplImage *first_frame; // Primer frame
	IplImage *frame, *hsv_frame;
	CvCapture *video;
	FILE *kernels;
	char *source_str;
	size_t source_size, work_items;

	// OpenCL runtime configuration
	unsigned num_devices;
	cl_platform_id platform_ids[3];
	cl_uint ret_num_platforms;
	cl_device_id device_id;
	cl_context context = NULL;
	cl_command_queue command_queue;
	cl_program program = NULL;
	cl_int ret;
	cl_kernel kernelHISTO;
	cl_event kernel_event, finish_event;
	cl_mem objFRAME, objHISTO;

	// Abrimos el fichero que contiene el kernel
	fopen_s(&kernels, "histoGPU.cl", "r");
	if (!kernels) {
		fprintf(stderr, "Fallo al cargar el kernel\n");
		exit(-1);
	}	
	source_str = (char *) malloc(0x100000);
	source_size = fread(source_str, 1, 0x100000, kernels);
	fclose(kernels);

	// Obtenemos los IDs de las plataformas disponibles
	if( clGetPlatformIDs(3, platform_ids, &ret_num_platforms) != CL_SUCCESS) {
		printf("No se puede obtener id de la plataforma");
		return -1;
	}

	// Intentamos obtener un dispositivo GPU soportado
	if( clGetDeviceIDs(platform_ids[0], CL_DEVICE_TYPE_GPU, 1, &device_id, &num_devices) != CL_SUCCESS) {
		printf("No se puede obtener id del dispositivo");
		return -1;
	}
	clGetDeviceInfo(device_id, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(cl_uint), &work_items, NULL);
 
	// Creación de un contexto OpenCL
	context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret);
 
	// Creación de una cola de comandos
	command_queue = clCreateCommandQueue(context, device_id, CL_QUEUE_PROFILING_ENABLE, &ret);

	// Creación de un programa kernel desde un fichero de código
	program = clCreateProgramWithSource(context, 1, (const char **)&source_str, (const size_t *)&source_size, &ret);
	ret = clBuildProgram(program, 1, &device_id, "-cl-nv-verbose", NULL, NULL);
	if (ret != CL_SUCCESS) {
		size_t len;
		char buffer[2048];
		printf("Error: ¡Fallo al construir el programa ejecutable!\n");
		clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &len);
		printf("%s", buffer);
		exit(-1);
	}

	// Creación del kernel OpenCL
	kernelHISTO = clCreateKernel(program, "calc_histo", &ret);

	// Abrimos el fichero de video y leemos el primer frame
	video = cvCaptureFromFile( argv[1] );
	if( !video ) {
		printf("No se pudo abrir el fichero de video %s\n", &argv[1]);
		exit(-1);
	}

	first_frame = cvQueryFrame( video );
	hsv_frame = cvCreateImage( cvGetSize(first_frame), IPL_DEPTH_32F, 3 );
	cvConvertScale( first_frame, hsv_frame, 1.0 / 255.0, 0 );
	cvCvtColor( hsv_frame, hsv_frame, CV_BGR2HSV );

	// Creamos el buffer para los frames y el histograma
	float *histo = (float*) _aligned_malloc(HTAM * sizeof(float), 64);
	objFRAME = clCreateBuffer(context, CL_MEM_READ_ONLY, hsv_frame->imageSize, NULL, &ret);
	objHISTO = clCreateBuffer(context, CL_MEM_READ_WRITE, HTAM * sizeof(float), NULL, &ret);
	memset(histo, 0.0f, HTAM * sizeof(float));
	const size_t global_work_size = work_items * 1024;
	const size_t local_work_size = 1024;

	// Transferimos el frame al dispositivo
	cl_event write_event[2];
	ret = clEnqueueWriteBuffer(command_queue, objFRAME, CL_FALSE, 0, hsv_frame->imageSize, hsv_frame->imageData, 0, NULL, &write_event[0]);
	ret = clEnqueueWriteBuffer(command_queue, objHISTO, CL_FALSE, 0, HTAM * sizeof(float), histo, 0, NULL, &write_event[1]);

	// Establecemos los argumentos del kernel
	ret = clSetKernelArg(kernelHISTO, 0, sizeof(cl_mem), &objHISTO);
	ret = clSetKernelArg(kernelHISTO, 1, sizeof(cl_mem), &objFRAME);
	ret = clSetKernelArg(kernelHISTO, 2, sizeof(int), &hsv_frame->widthStep);
	ret = clSetKernelArg(kernelHISTO, 3, sizeof(int), &hsv_frame->height);
	ret = clSetKernelArg(kernelHISTO, 4, sizeof(int), &hsv_frame->width);

	// Ejecutamos el kernel. 128 work-items por cada work-group o unidad de cómputo
	ret = clEnqueueNDRangeKernel(command_queue, kernelHISTO, 1, NULL, &global_work_size, &local_work_size, 2, write_event, &kernel_event);

	// Leemos los resultados
	ret = clEnqueueReadBuffer(command_queue, objHISTO, CL_FALSE, 0, HTAM * sizeof(float), histo, 1, &kernel_event, &finish_event);
	
	// Esperamos a que termine de leer los resultados
	clWaitForEvents(1, &finish_event);

	// Obtenemos el tiempo del kernel y de las transferencias Pcie
	cl_ulong totalKernel = getStartEndTime(kernel_event);
	cl_ulong totalPcie = getStartEndTime(write_event[0]) + getStartEndTime(write_event[1]) + getStartEndTime(finish_event);
	cvReleaseImage( &hsv_frame );

	// Recordar que frame no se puede liberar debido al cvQueryFrame
	while( frame = cvQueryFrame( video ) ) {
		hsv_frame = cvCreateImage( cvGetSize(frame), IPL_DEPTH_32F, 3 );
		cvConvertScale( frame, hsv_frame, 1.0 / 255.0, 0 );
		cvCvtColor( hsv_frame, hsv_frame, CV_BGR2HSV );
		memset(histo, 0.0f, HTAM * sizeof(float));
		ret = clEnqueueWriteBuffer(command_queue, objFRAME, CL_FALSE, 0, hsv_frame->imageSize, hsv_frame->imageData, 0, NULL, &write_event[0]);
		ret = clSetKernelArg(kernelHISTO, 0, sizeof(cl_mem), &objHISTO);
		ret = clSetKernelArg(kernelHISTO, 1, sizeof(cl_mem), &objFRAME);
		ret = clSetKernelArg(kernelHISTO, 2, sizeof(int), &hsv_frame->widthStep);
		ret = clSetKernelArg(kernelHISTO, 3, sizeof(int), &hsv_frame->height);
		ret = clSetKernelArg(kernelHISTO, 4, sizeof(int), &hsv_frame->width);
		ret = clEnqueueNDRangeKernel(command_queue, kernelHISTO, 1, NULL, &global_work_size, &local_work_size, 2, write_event, &kernel_event);
		ret = clEnqueueReadBuffer(command_queue, objHISTO, CL_FALSE, 0, HTAM * sizeof(float), histo, 1, &kernel_event, &finish_event);
		clWaitForEvents(1, &finish_event);
		totalKernel += getStartEndTime(kernel_event);
		totalPcie += (getStartEndTime(write_event[0]) + getStartEndTime(write_event[1]) + getStartEndTime(finish_event));
		cvReleaseImage( &hsv_frame );
	}

	const double end_time = getCurrentTimestamp();

	// Obtenemos el tiempo consumido por el programa, el kernel y las transferencias de memoria
	printf("\nTiempo total del programa: %0.3f ms\n", (end_time - start_time) * 1e3);
	printf("Tiempo total consumido por el kernel: %0.3f ms\n", double(totalKernel) * 1e-6);
	printf("Tiempo total consumido en transferencias Pcie: %0.3f ms\n", double(totalPcie) * 1e-6);

	// Liberamos todos los recursos usados (kernels, frames y objetos OpenCL)
	clReleaseEvent(kernel_event);
	clReleaseEvent(finish_event);
	clReleaseEvent(write_event[0]);
    clReleaseEvent(write_event[1]);
	cvReleaseCapture( &video );
	clReleaseMemObject(objFRAME);
	clReleaseMemObject(objHISTO);
	clReleaseKernel(kernelHISTO);
	clReleaseCommandQueue(command_queue);
	clReleaseProgram(program);
	clReleaseContext(context);
}