//Run the CL kernel //Buffer I/O must be handled separately void runCLKernels(size_t runWidth) { //cout << "Running " << runWidth << " threads." << endl; size_t globalThreads[1]; size_t localThreads[1]; localThreads[0]= threadsPerWorkgroup; globalThreads[0] = runWidth; cl_event exec_events[1];//An event that tracks kernel execution status = clEnqueueNDRangeKernel( commandQueue, kernel, 1, NULL, globalThreads, localThreads, 0, NULL, &exec_events[0]); if(status != CL_SUCCESS) exitOnError("Enqueueing kernel onto command queue.(clEnqueueNDRangeKernel)"); status = clWaitForEvents(1,&exec_events[0]); if(status != CL_SUCCESS) exitOnError("Waiting for kernel run to finish.(clWaitForEvents)"); status = clReleaseEvent(exec_events[0]); if(status != CL_SUCCESS) exitOnError("Releasing event object exec_events[0].(clWaitForEvents)"); }
int main() { signal(SIGINT, handler_int); signal(SIGCHLD, handler_kill); int sock; int handle; int count; char buf[255] = "\0"; struct sockaddr_in server; sock = socket(AF_INET, SOCK_STREAM, 0); if(sock < 0) exitOnError("Socket() serveur : Nok \n"); else fprintf(stdout, "Socket() serveur : ok \n"); server.sin_family = AF_INET; server.sin_port = htons(5990); //inet_aton("127.0.0.1", (struct in_addr *) &server.sin_addr.s_addr); // Lorsqu'on indique INADDR_ANY lors de l'attachement, la socket sera // affectée à toutes les interfaces locales. Si on invoque listen(2) ou // connect(2) sur une socket non affectée, elle est automatiquement attachée // à un port libre aléatoire, avec l'adresse locale fixée sur INADDR_ANY. server.sin_addr.s_addr = INADDR_ANY; if (bind(sock, (struct sockaddr *) &server, sizeof(server)) < 0) exitOnError("bind() serveur : Nok \n"); else fprintf(stdout, "bind() serveur : ok \n"); if (listen(sock, 2) < 0) exitOnError("listen() serveur : Nok \n"); else fprintf(stdout, "listen() serveur : ok \n"); while((handle = accept(sock, NULL, NULL)) >= 0) { if (fork() == 0) { close(sock); count = read(handle, &buf, sizeof(buf)); printf("Recu %d charactères : %s \n",count, buf); close(handle); exit(EXIT_SUCCESS); } close(handle); } close(sock); exit(EXIT_SUCCESS); }
/*Build Minimax Tree of fixed depth via DFS*/ MinimaxNode *getMinimaxTreeFixedDepth(Game *game, int depth, Move *move, Color uCol) { MinimaxNode *curr = (MinimaxNode*)malloc(sizeof(MinimaxNode)); if (curr == NULL) exitOnError("malloc"); curr->game = (Game*)malloc(sizeof(Game)); if (curr->game == NULL) exitOnError("malloc"); struct ListNode *moves; int i = 0; curr->depth = depth; copyGame(game, curr->game); curr->sons = NULL; curr->sonsK = 0; if (move != NULL) { updateBoard(curr->game, move); } if (depth == 1) { curr->move = move; } else { freeMove(move); curr->move = NULL; } if (depth == game->difficulty) { return curr; } if ((depth % 2 == 0 && uCol == WHITE) || (depth % 2 == 1 && uCol == BLACK)) { moves = getMoves(curr->game, WHITE); } else { moves = getMoves(curr->game, BLACK); } int size = listSize(moves); curr->sonsK = size; if (!size) { free(moves); return curr; } else { curr->sons = (MinimaxNode**)malloc(sizeof(MinimaxNode)*size); if (curr->sons == NULL) exitOnError("malloc"); struct ListNode *temp = moves; for (i = 0; i < size; i++) { Move* tMove = copyMove(temp->move); curr->sons[i] = getMinimaxTreeFixedDepth(curr->game, depth + 1, tMove, uCol); temp = temp->next; } freeList(moves); } return curr; }
cairo_font_face_t *load_font_face() { FT_Library lib; FT_Face face; FT_Error error; cairo_font_face_t *cr_face; char *path = "/Users/sseefried/code/games/epidemic-game/GoodDog.otf"; error = FT_Init_FreeType(&lib); exitOnError(error); error = FT_New_Face(lib, path, 0, &face); exitOnError(error); cr_face = cairo_ft_font_face_create_for_ft_face(face, 0); return cr_face; }
//Reads data from output buffers void readBuffers(cl_uint offset,cl_uint entriesToRead) { //cout << "Reading " << entriesToRead << " entries from buffers with offset "<< offset << endl; status = clEnqueueReadBuffer( commandQueue, cartesian_buf, CL_TRUE, 0, entriesToRead * sizeof(cl_double8), cartesian + offset, 0, NULL, NULL); if(status != CL_SUCCESS) exitOnError("clEnqueueReadBuffer failed.(clEnqueueReadBuffer)\n"); status = clEnqueueReadBuffer( commandQueue, barycentric_buf, CL_TRUE, 0, entriesToRead * sizeof(cl_double4), barycentric + offset, 0, NULL, NULL); if(status != CL_SUCCESS) exitOnError("clEnqueueReadBuffer failed.(clEnqueueReadBuffer)\n"); status = clEnqueueReadBuffer( commandQueue, parametric_buf, CL_TRUE, 0, entriesToRead * sizeof(cl_double2), parametric + offset, 0, NULL, NULL); if(status != CL_SUCCESS) exitOnError("clEnqueueReadBuffer failed.(clEnqueueReadBuffer)\n"); }
/* * General method for tests that erode an input image with a morphMask and write the result to filenameOut if != NULL */ void testErosion(cudaPaddedImage input, cudaImage output, rect2d roi, morphMask mask, const char* filenameOut, const char* textOnError) { performErosion(getData(input), getPitch(input), getData(output), getPitch(output), roi, mask, input.border); if (filenameOut != NULL) { float *host_out = copyImageToHost(output); printf("output width: %d , height: %d\n", output.width, output.height); savePGM(filenameOut, host_out, output.width, output.height); freeHost(host_out, PINNED); } exitOnError(textOnError); }
/*Determine whether given Move exposes King, if not - Move is valid*/ int isValidMove(Game *game, Move *move){ int res = 0; Color col = getColFromLoc(game->board, move->source); col = oppositeCol(col); Game *copyG = (Game*)malloc(sizeof(Game)); if (copyG== NULL) exitOnError("malloc"); copyGame(game, copyG); updateBoard(copyG, move); if (!canKillKing(copyG, col)){ res = 1; } free(copyG); return res; }
/*Get Moves with Maximum Score*/ ListNode* getMaximumMoves(MinimaxNode*root) { ListNode *res = (ListNode*)malloc(sizeof(ListNode)); if (res == NULL) exitOnError("malloc"); res->move = NULL; res->next = NULL; int i = 0; for (i = 0; i < root->sonsK; i++) { if (root->sons[i]->val == root->val) { //printf("Found same val %d\n", root->val); Move* cMove = copyMove(root->sons[i]->move); addMoveToList(res, cMove); } } return res; }
//Dumps a compiled kernel to a binary file void dumpBinary(cl_program program,const char *kernelName) { //Get number of devices cl_uint deviceCount = 0; status = clGetProgramInfo(program,CL_PROGRAM_NUM_DEVICES,sizeof(cl_uint),&deviceCount,NULL); if(status != CL_SUCCESS) exitOnError("Getting number of devices for the program(clGetProgramInfo)"); //Get sizes of compiled binaries for said devices size_t *binSize = (size_t*)malloc(sizeof(size_t)*deviceCount); status = clGetProgramInfo(program,CL_PROGRAM_BINARY_SIZES,(sizeof(size_t)*deviceCount),binSize,NULL); if(status != CL_SUCCESS) exitOnError("Getting binary sizes for the program(clGetProgramInfo)"); char **bin = ( char**)malloc(sizeof(char*)*deviceCount); for(cl_uint i = 0;i<deviceCount;i++) bin[i] = (char*)malloc(binSize[i]); //Retrieve compiled binaries status = clGetProgramInfo(program,CL_PROGRAM_BINARIES,(sizeof(size_t)*deviceCount),bin,NULL); if(status != CL_SUCCESS) exitOnError("Getting program binaries(clGetProgramInfo)"); //Export binaries to files, appending CL_DEVICE_NAME to each filename char binFileName[MAX_NAME_LENGTH]; for(cl_uint i = 0;i<deviceCount;i++) { char deviceName[MAX_NAME_LENGTH]; status = clGetDeviceInfo(devices[i],CL_DEVICE_NAME,MAX_NAME_LENGTH,deviceName,NULL); if (status != CL_SUCCESS) exitOnError("Cannot get device name for given device number"); printf("Binary image of kernel %s created for device %s.\n",kernelName,deviceName); sprintf(binFileName,"%s_%s.elf",kernelName,deviceName); std::fstream outBinFile(binFileName, (std::fstream::out | std::fstream::binary)); if(outBinFile.fail()) exitOnError("Cannot open binary file"); outBinFile.write(bin[i],binSize[i]); outBinFile.close(); } for(cl_uint i = 0;i<deviceCount;i++) free(bin[i]); }
/*Return possible Moves for Color*/ ListNode *getCandidateMoves(Game *game, Color col){ ListNode *temp = (ListNode*)malloc(sizeof(ListNode)); if (temp == NULL) exitOnError("malloc"); temp->move = NULL; temp->next = NULL; int i, j; for (i = 0; i < BOARD_SIZE; i++){ for (j = 0; j < BOARD_SIZE; j++){ if (sameCol(game->board[i][j], col)){ Location *loc = setLocation(i, j); getMovesSinglePiece(game, loc, temp); free(loc); } } } return temp; }
/*Determine whether Color has legal Moves on Board*/ int hasMoves(Game *game, Color col){ ListNode *temp = (ListNode*)malloc(sizeof(ListNode)); if (temp == NULL) exitOnError("malloc"); int flag = 0; temp->move = NULL; temp->next = NULL; ListNode *head = temp; int i, j; for (i = 0; i < BOARD_SIZE; i++){ for (j = 0; j < BOARD_SIZE; j++){ if (sameCol(game->board[i][j], col)){ Location *loc = setLocation(i, j); flag = getMovesSinglePiece(game, loc, temp); free(loc); } if (flag){ freeList(head); return 1; } } } freeList(head); return 0; }
/*Build Minimax Tree for Best Difficulty using BFS Algorithm*/ MinimaxNode *getMinimaxTreeBestDepth(Game *game, Color uCol) { MinimaxNode *root = (MinimaxNode*)malloc(sizeof(MinimaxNode)); if (root == NULL)exitOnError("malloc"); root->game = (Game*)malloc(sizeof(Game)); if (root->game == NULL) exitOnError("malloc"); root->val = 0; MinimaxNode *curr; ListNode *moves; int i; int leavesLocal = 1; Queue *q = setQueue(); /*Create empty Queue for BFS Traversing*/ int size = 0; root->depth = 0; root->move = NULL; copyGame(game, root->game); root->sons = NULL; root->sonsK = 0; enqueue(q, root); /*While Queue is not empty and there are less than MAX_BOARDS_TO_EVAL Leaves in Tree*/ while (q->size&&leavesLocal + size <= MAX_BOARDS_TO_EVAL) { curr = dequeue(q); /*Pop from Queue*/ if (curr->depth % 2 == 0)moves = getMoves(curr->game, uCol); /*Get possible Moves at current Board state*/ else moves = getMoves(curr->game, oppositeCol(uCol)); size = listSize(moves); if (!size) { free(moves); continue; } curr->sons = (MinimaxNode**)malloc(sizeof(MinimaxNode)*size); if (curr->sons == NULL) exitOnError("malloc"); curr->sonsK = size; ListNode *temp = moves; for (i = 0; i < size; i++) { /*Add Nodes for each possible Move*/ curr->sons[i] = (MinimaxNode*)malloc(sizeof(MinimaxNode)); if (curr->sons[i] == NULL) exitOnError("malloc"); curr->sons[i]->game = (Game*)malloc(sizeof(Game)); if (curr->sons[i]->game == NULL) exitOnError("malloc"); curr->sons[i]->val = 0; copyGame(curr->game, curr->sons[i]->game); Move* tMove = copyMove(temp->move); updateBoard(curr->sons[i]->game, tMove); curr->sons[i]->depth = curr->depth + 1; if (curr->sons[i]->depth == 1) { curr->sons[i]->move = tMove; } else { freeMove(tMove); curr->sons[i]->move = NULL; } curr->sons[i]->sons = NULL; curr->sons[i]->sonsK = 0; enqueue(q, curr->sons[i]); /*Push to Queue*/ temp = temp->next; } /*Update amount of Leaves in Tree*/ freeList(moves); leavesLocal += size; if (size) leavesLocal--; } freeQueue(q); return root; }
void exitOnNULLPointer(void *ptr){// Test for and exit on NULL pointer if (!ptr) exitOnError(); }
//Releases all CL objects void cleanupCL(void) { status = clReleaseKernel(kernel); if(status != CL_SUCCESS) exitOnError("In clReleaseKernel \n"); status = clReleaseProgram(program); if(status != CL_SUCCESS) exitOnError("In clReleaseProgram\n"); status = clReleaseMemObject(orig_buf); if(status != CL_SUCCESS) exitOnError("In clReleaseMemObject (orig_buf)\n"); status = clReleaseMemObject(dir_buf); if(status != CL_SUCCESS) exitOnError("In clReleaseMemObject (dir_buf)\n"); status = clReleaseMemObject(vert0_buf); if(status != CL_SUCCESS) exitOnError("In clReleaseMemObject (vert0_buf)\n"); status = clReleaseMemObject(vert1_buf); if(status != CL_SUCCESS) exitOnError("In clReleaseMemObject (vert1_buf)\n"); status = clReleaseMemObject(vert2_buf); if(status != CL_SUCCESS) exitOnError("In clReleaseMemObject (vert2_buf)\n"); status = clReleaseMemObject(vert3_buf); if(status != CL_SUCCESS) exitOnError("In clReleaseMemObject (vert3_buf)\n"); status = clReleaseMemObject(cartesian_buf); if(status != CL_SUCCESS) exitOnError("In clReleaseMemObject (cartesian_buf)\n"); status = clReleaseMemObject(barycentric_buf); if(status != CL_SUCCESS) exitOnError("In clReleaseMemObject (barycentric_buf)\n"); status = clReleaseMemObject(parametric_buf); if(status != CL_SUCCESS) exitOnError("In clReleaseMemObject (parametric_buf)\n"); status = clReleaseCommandQueue(commandQueue); if(status != CL_SUCCESS) exitOnError("In clReleaseCommandQueue\n"); status = clReleaseContext(context); if(status != CL_SUCCESS) exitOnError("In clReleaseContext\n"); if(devices != NULL) { free(devices); devices = NULL; } }
//Run the CL kernel //Handles buffer IO void runCLKernelsWithIO(void) { size_t globalThreads[1]; size_t localThreads[1]; localThreads[0]= threadsPerWorkgroup; //Break up kernel execution to 1 exec per WORK_ITEM_LIMIT work items. cl_uint remainingWidth = paddedWidth; cl_uint offset = 0; cl_event exec_events[1];//An event that tracks kernel execution while(remainingWidth > WORK_ITEM_LIMIT) { writeBuffers(offset,WORK_ITEM_LIMIT); //Enqueue a kernel run call. globalThreads[0] = WORK_ITEM_LIMIT; status = clEnqueueNDRangeKernel( commandQueue, kernel, 1, NULL, globalThreads, localThreads, 0, NULL, &exec_events[0]); if(status != CL_SUCCESS) exitOnError("Enqueueing kernel onto command queue.(clEnqueueNDRangeKernel)"); status = clWaitForEvents(1,&exec_events[0]); if(status != CL_SUCCESS) exitOnError("Waiting for kernel run to finish.(clWaitForEvents)"); readBuffers(offset,WORK_ITEM_LIMIT); remainingWidth -= WORK_ITEM_LIMIT; offset += WORK_ITEM_LIMIT; } //Final kernel run call for remaining work_items globalThreads[0] = remainingWidth; writeBuffers(offset,remainingWidth); status = clEnqueueNDRangeKernel( commandQueue, kernel, 1, NULL, globalThreads, localThreads, 0, NULL, &exec_events[0]); if(status != CL_SUCCESS) exitOnError("Enqueueing kernel onto command queue.(clEnqueueNDRangeKernel)"); status = clWaitForEvents(1,&exec_events[0]); if(status != CL_SUCCESS) exitOnError("Waiting for kernel run to finish.(clWaitForEvents)"); readBuffers(offset,remainingWidth); status = clReleaseEvent(exec_events[0]); if(status != CL_SUCCESS) exitOnError("Releasing event object exec_events[0].(clWaitForEvents)"); }
//Load CL file, compile, link CL source //Try to find a precompiled binary //Build program and kernel objects void makeCLKernel(const char *kernelName,int deviceNum) { //Kernel Loading/Compilation //Attempt to load precompiled binary file for target device char binFileName[MAX_NAME_LENGTH]; sprintf(binFileName,"%s_%s.elf",kernelName,deviceName); std::fstream inBinFile(binFileName, (ios::in|ios::binary|ios::ate)); //Compile if(inBinFile.fail()) { inBinFile.close(); printf("No binary image found for specified kernel.Compiling from source.\n"); char sourceFileName[MAX_NAME_LENGTH]; sprintf(sourceFileName,"%s.cl",kernelName); std::string sourceStr = convertToString(sourceFileName); if (sourceStr == "NULL") exitOnError("Cannot read kernel source file"); const char *source = (char*)sourceStr.c_str(); size_t sourceSize[] = { strlen(source) }; program = clCreateProgramWithSource( context, 1, &source, sourceSize, &status); if(status != CL_SUCCESS) exitOnError("Loading Source into cl_program (clCreateProgramWithSource)"); // create a cl program executable for all the devices specified status = clBuildProgram(program, 0, NULL, NULL, NULL, NULL); if (status != CL_SUCCESS) { //Build failed. printf("Error building program(clBuildProgram)\nCompiler Output:\n"); //Retrieve the size of the build log char* build_log; size_t log_size; status = clGetProgramBuildInfo(program, devices[deviceNum], CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size); if(status != CL_SUCCESS) exitOnError("Cannot get compiler log size.(clGetProgramBuildInfo)"); build_log = (char*)malloc(log_size+1); // Get and display the build log status = clGetProgramBuildInfo(program, devices[deviceNum], CL_PROGRAM_BUILD_LOG, log_size, build_log, NULL); if(status != CL_SUCCESS) exitOnError("Cannot get compiler log.(clGetProgramBuildInfo)"); build_log[log_size] = '\0'; printf("%s\n",build_log); free (build_log); printf("End of Compiler Output.\n"); exit(1); } //Export Binary Images to file dumpBinary(program,kernelName); }else{ size_t *binSize = (size_t*)malloc(sizeof(size_t)); char* bin; *binSize = inBinFile.tellg(); inBinFile.seekg (0, ios::beg); bin = new char[*binSize]; inBinFile.read(bin,*binSize); inBinFile.close(); program = clCreateProgramWithBinary( context, 1, &devices[deviceNum], binSize, (const unsigned char **)&bin, NULL, &status); if(status != CL_SUCCESS) exitOnError("Loading Binary into cl_program (clCreateProgramWithBinary)"); // create a cl program executable for all the devices specified status = clBuildProgram(program,1, &devices[deviceNum], NULL, NULL, NULL); if (status != CL_SUCCESS) { //Build failed. printf("Error building program(clBuildProgram)\nCompiler Output:\n"); //Retrieve the size of the build log char* build_log; size_t log_size; status = clGetProgramBuildInfo(program, devices[deviceNum], CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size); if(status != CL_SUCCESS) exitOnError("Cannot get compiler log size.(clGetProgramBuildInfo)"); build_log = (char*)malloc(log_size+1); // Get and display the build log status = clGetProgramBuildInfo(program, devices[deviceNum], CL_PROGRAM_BUILD_LOG, log_size, build_log, NULL); if(status != CL_SUCCESS) exitOnError("Cannot get compiler log.(clGetProgramBuildInfo)"); build_log[log_size] = '\0'; printf("%s\n",build_log); free (build_log); printf("End of Compiler Output."); exit(1); } } // get a kernel object handle for a kernel with the given name kernel = clCreateKernel(program,kernelName,&status); if(status != CL_SUCCESS) exitOnError("Creating Kernel from program. (clCreateKernel)"); }
//OpenCL related initialization //Create Context, Device list, Command Queue void initializeCL(int deviceNum) { size_t deviceListSize; //Identify available platforms and select one cl_uint numPlatforms; cl_platform_id platform = NULL; status = clGetPlatformIDs(0, NULL, &numPlatforms); if(status != CL_SUCCESS) exitOnError("Getting Platforms. (clGetPlatformsIDs)"); if(numPlatforms > 0) { cl_platform_id* platforms = (cl_platform_id *)malloc(numPlatforms*sizeof(cl_platform_id)); status = clGetPlatformIDs(numPlatforms, platforms, NULL); if(status != CL_SUCCESS) exitOnError("Getting Platform Ids. (clGetPlatformsIDs)"); for(cl_uint i=0; i < numPlatforms; ++i) { char pbuff[MAX_NAME_LENGTH]; status = clGetPlatformInfo( platforms[i], CL_PLATFORM_VENDOR, sizeof(pbuff), pbuff, NULL); if(status != CL_SUCCESS) exitOnError("Getting Platform Info. (clGetPlatformInfo)"); platform = platforms[i]; //AMD or Nvidia Platforms are preferred //If none of them are found the first available platform is used if((!strcmp(pbuff, "Advanced Micro Devices, Inc.")) ||(!strcmp(pbuff,"NVIDIA Corporation"))) { break; } } delete platforms; } if(NULL == platform) exitOnError("NULL platform found."); cl_context_properties cps[3] = { CL_CONTEXT_PLATFORM, (cl_context_properties)platform, 0 }; // Create an OpenCL context context = clCreateContextFromType(cps, CL_DEVICE_TYPE_ALL, NULL, NULL, &status); if(status != CL_SUCCESS) exitOnError("Creating Context. (clCreateContextFromType)."); //First, get the size of device list data status = clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &deviceListSize); if(status != CL_SUCCESS) exitOnError("Getting Context Info(device list size, clGetContextInfo)."); //Detect OpenCL devices devices = (cl_device_id *)malloc(deviceListSize); if(deviceListSize == 0) exitOnError("No devices found."); if((deviceListSize/sizeof(size_t)) < (deviceNum +1)) exitOnError("No device found for given device number."); //Now, get the device list data status = clGetContextInfo( context, CL_CONTEXT_DEVICES, deviceListSize, devices, NULL); if(status != CL_SUCCESS) exitOnError("Getting Context Info (device list, clGetContextInfo)."); //Create an OpenCL command queue on the device with the given deviceNum commandQueue = clCreateCommandQueue( context, devices[deviceNum], 0, &status); if(status != CL_SUCCESS) exitOnError("Creating Command Queue. (clCreateCommandQueue)."); //Identify the target device status = clGetDeviceInfo(devices[deviceNum],CL_DEVICE_NAME,MAX_NAME_LENGTH,deviceName,NULL); if (status != CL_SUCCESS) exitOnError("Cannot get device name for given device number(clGetDeviceInfo)"); printf("Using Device:%s\n",deviceName); //Identify the device's vendor (used to set threadsPerWorkgroup) char deviceVendorName[MAX_NAME_LENGTH]; status = clGetDeviceInfo(devices[deviceNum],CL_DEVICE_VENDOR,MAX_NAME_LENGTH * sizeof(char),deviceVendorName,NULL); if (status != CL_SUCCESS) exitOnError("Cannot get device vendor's name for given device number(clGetDeviceInfo)"); //Identify the device's type (used to set threadsPerWorkgroup) cl_device_type deviceType; status = clGetDeviceInfo(devices[deviceNum],CL_DEVICE_TYPE,sizeof(cl_device_type),&deviceType,NULL); if (status != CL_SUCCESS) exitOnError("Cannot get device type for given device number(clGetDeviceInfo)"); if (deviceType == CL_DEVICE_TYPE_CPU) threadsPerWorkgroup = 1; else if(!strcmp(deviceVendorName,"Advanced Micro Devices, Inc.")) threadsPerWorkgroup = 64; else if(!strcmp(deviceVendorName,"NVIDIA Corporation")) threadsPerWorkgroup = 32; }
/** * This is called once by main() to interpret the command line: * It sets m_iNumLap, m_iNumCar, real_speed and trackfile[], and options. * RARS command line options: ( - or / signifies an option) * -h or -H or -? shows this help screen (/ may be used in place of -) * -d meaning drivers (followed by space and then list of driver's names) * -D meaning ignore drivers (followed by space and list of names to not use) * -f meaning fastest that computer can compute (default is realistic) * -l meaning followed by race length in miles. * -mp meaning playback movie (can be followed by filename, eg. -mpmovie) * -mr meaning record movie (can be followed by filename, eg. -mrmovie) * -nd meaning no display (there is a results report written to RAC.OUT) * -ni meaning keystrokes supplied by computer, no waiting. * -nr meaning no randomization of r.v.g. (same initial seed every time) * (-nr may be followed by a seed value, without a space) * -nR meaning car motion is deterministic, and also r.v.g. not randomized * -o meaning order (starting order as given in driver list or as compiled) * -p meaning practice, followed by the number of practice laps. * -q meaning qualifying mode (1-fastest lap, 2-avg speed) * -ql meaning qualifying laps, how many * -qr meaning qualifying sessions, how many * -r meaning races, how many * -s meaning surface type, s0 = loose surface, s1 = harder surface, default 0 * -sr meaning starting rows. Default is given in track file. * -v meaning Just show the version and exit. * -z meaning disable "side vision" for all drivers * * @param argc (in) from maim() * @param argv (in) from maim() */ void Args::GetArgs(int argc, char* argv[]) { int cur_arg, i; char c; char *ptr; // will point to current argument being processed char *tmp_ptr; // Used for track names int num_count = 0; // how many numerical arguments have been seen char option; // holds the option code char lastext[81]; // the last text argument processed lastext[0] = 0; int car_param_idx = 0; // номер первого аргумента описывающего машину(id) в массиве аргументов Driver * temp_drv; int n, k; // process each argument in turn: for(cur_arg=1; cur_arg<argc; cur_arg++) // once for each argument { ptr = argv[cur_arg]; c = *ptr; if(cur_arg == 1) // первый аргумент - интервал логгирования { log_interval = atoi(ptr); if(log_interval == 0) log_interval = -1; continue; } else if(cur_arg == 2) // второй аргумент - путь к логу { if(log_interval > 0) log_file = ptr; continue; } if(c == '-' || c == '/') // is this an option request? { ++ptr; option = *ptr; // grab the option code ++ptr; // point to char after code switch(option) // which one? { case '?': case 'h': case 'H': // H for Help PrintHelpFile(); exit(0); case 'd': // d for drivers // re-arrange drivers[] array according to names in command line car_param_idx = cur_arg; for( n=0; n<MAX_CARS; n++ ) { car_param_idx = ++car_param_idx; if (car_param_idx == argc) { break; } char* car_id = argv[car_param_idx++]; ptr = argv[car_param_idx++]; if((i = find_name(ptr)) < 0) { //TODO: it must be possible to replay with unknown drivers. if( m_iMovieMode != MOVIE_PLAYBACK ) exitOnError("Driver %s was not found.", ptr); /* strcpy(lastext, ptr); --cur_arg; break; */ } int idx = find_name_from_idx(ptr, n); double pm = atof(argv[car_param_idx]); car_param_idx++; unsigned long init_damage = strtol(argv[car_param_idx], NULL, 10); if (idx > 0) { temp_drv = drivers[n]; drivers[n] = drivers[idx]; drivers[idx] = temp_drv; } else drivers[n] = getDriver(ptr); drivers[n]->id = car_id; drivers[n]->init_damage = init_damage; drivers[n]->pm = pm; } cur_arg = car_param_idx; break; case 'D': // D for drivers to eliminate // re-arrange drivers[] array according to names in command line for(n=0; n<MAX_CARS; n++) { ++cur_arg; if (cur_arg == argc) { break; } ptr = argv[cur_arg]; if((i = find_name(ptr)) < 0) { strcpy(lastext, ptr); --cur_arg; break; } temp_drv = drivers[i]; for(k=i; k<MAX_CARS-1; k++) { drivers[k] = drivers[k+1]; } drivers[MAX_CARS-1] = temp_drv; } break; case 'f': // f for fast if (isdigit(*ptr)) { draw.m_iFastDisplay = atoi(ptr); } else { draw.m_iFastDisplay = -1; } break; case 'l': // l for race length (in miles) if (isdigit(*ptr)) { m_iRaceLength = atol(ptr); } break; case 'm': if ((*ptr == 'p') || (*ptr == 'r')) { // get movie filename if (*(ptr+1)) { strcpy( m_sMovieName, ptr+1 ); char *p = strchr( m_sMovieName,'.' ); if( p ) { *p = 0; } } m_iMovieMode = (*ptr == 'r'? MOVIE_RECORD : MOVIE_PLAYBACK); } break; case 'n': // n for no or non if(*ptr == 'r') // nr for non-random { m_bRndmiz = false; if(*(ptr+1) != ' ') // this when -nr has a seed given { m_iSeed = (long)atol(ptr+1); } } else if(*ptr == 'R') // nR for even more non-random { m_bRndmiz = false; m_bRandomMotion = false; } else if(*ptr == 'd') // nd for no display { draw.m_bDisplay = false; } break; case 'o': // o for order m_bKeepOrder = true; break; case 'p': // p for practice m_bPractice = 1; // practice mode if(isdigit(*ptr)) { m_iNumPracticeLap = atol(ptr); // lap count entered without space } break; case 'q': { // Do ugly adjustment to new structure int qualifying = 1; if (isdigit(*ptr)) { qualifying = atoi(ptr);// set another mode by 0, 1 or 2 } else if(*ptr == '\0') { if(!qualifying) { qualifying = 1; // set default if only -q } } else if (*ptr == 'l') // ql for qual lap count { if(*(ptr+1) != ' ') { m_iNumQualLap = atol(ptr+1); if(!qualifying) { qualifying = 1;// set default } } } else if (*ptr == 'r') // qr for qual sessions or { if(*(ptr+1) != ' ') // qual Rounds { m_iNumQualSession = atoi(ptr+1); if(!qualifying) { qualifying = 1;// set default } } } // Adjust to new structure if (qualifying == 0) { m_bQual = false; } else if (qualifying == 1) { m_bQual = true; } else if (qualifying == 2) { m_bQual = true; m_iQualMode = QUAL_AVERAGE_SPEED; } break; } case 'r': // r for races if(*ptr == '\0') // a space after the - causes a new argument { ++cur_arg; // this is because spaces increase the arg count ptr = argv[cur_arg]; } m_iNumRace = atol(ptr); // number of races entered without space break; case 's': if(*ptr == 'r') // sr for starting rows { m_iStartRows = atoi(ptr+1); } else { m_iSurface = atoi(ptr); } break; case 'v': // v for version VersionReport(); exit(0); case 'z': // side vision m_bGlobalSideVision = false; break; } // end switch() } // end if( c == '-') else if(c >= '0' && c <= '9') // is it a numerical argument? { if(!num_count) // is this the first such? { m_iNumCar = atoi(ptr); } else { m_iNumLap = atol(ptr); // if lap_count is explicitly defined, m_iRaceLength = 0; // don't use race_length value } ++num_count; } else // then its a text argument { if( m_iNumTrack<MAX_TRACKS ) { // tmp_ptr=new char[16]; // strcpy(tmp_ptr,argv[cur_arg]); // m_aTracks[m_iNumTrack++]=tmp_ptr; m_aTracks[m_iNumTrack++]=argv[cur_arg]; } else { cout<<"Max "<<MAX_TRACKS<<" tracks per series.."<<endl; } } } // end big for(;;) loop. // handle goofy command line input: if( m_iNumCar>MAX_CARS ) { m_iNumCar = MAX_CARS; } if( m_iNumCar<0 ) { m_iNumCar = 0; } if( m_iNumLap<0 ) { m_iNumLap = 0; // use race_length for finding lap_count } if(!m_iNumLap && m_iRaceLength<=0 ) { m_iRaceLength = 200; // negative lap_count was entered? } if( m_iNumQualLap<=0 ) { m_iNumQualLap=1; } if(m_iNumPracticeLap <= 0) { m_iNumPracticeLap = 1; } if( m_iNumTrack<=0 ) { tmp_ptr=new char[16]; strcpy(tmp_ptr,"rars.trk"); //the default trackfile m_aTracks[0]=tmp_ptr; m_iNumTrack = 1; } /* if(qualifying > 2 || qualifying < 0) { qualifying = 1; // only 0,1,2 allowed (not necessary anymore) } */ if( m_iStartRows<0 || m_iStartRows>8 ) // starting rows { m_iStartRows = 1; } if(draw.m_iFastDisplay < -1 ) { draw.m_iFastDisplay = 1; } if(!strcmp(m_aTracks[0], "season")) // read tracks from file { Track::readTrackNamesFromFile(); } // check to see if a bogus driver name was entered under the -d option: if(!lastext[0]) { return; // OK if nothing was captured } for(i=0; lastext[i]; i++) // OK if a number was captured { c = lastext[i]; if(c < '0' || c > '9') // is it a number? { break; // leave loop if not a number } } if(i == (int)strlen(lastext)) { return; // This when lastext contains only numbers } }
//Fills input buffers with data void writeBuffers(cl_uint offset,cl_uint entriesToWrite) { //cout << "Writing " << entriesToWrite << " entries into buffers with offset "<< offset << endl; status = clEnqueueWriteBuffer( commandQueue, orig_buf, CL_TRUE, 0, sizeof(cl_double4) * entriesToWrite, origin + offset, 0, NULL, NULL); if(status != CL_SUCCESS) exitOnError("Writing to input buffer. (orig_buf)"); status = clEnqueueWriteBuffer( commandQueue, dir_buf, CL_TRUE, 0, sizeof(cl_double4) * entriesToWrite, dir + offset, 0, NULL, NULL); if(status != CL_SUCCESS) exitOnError("Writing to input buffer. (dir_buf)"); status = clEnqueueWriteBuffer( commandQueue, vert0_buf, CL_TRUE, 0, sizeof(cl_double4) * entriesToWrite, vert0 + offset, 0, NULL, NULL); if(status != CL_SUCCESS) exitOnError("Writing to input buffer. (vert0_buf)"); status = clEnqueueWriteBuffer( commandQueue, vert1_buf, CL_TRUE, 0, sizeof(cl_double4) * entriesToWrite, vert1 + offset, 0, NULL, NULL); if(status != CL_SUCCESS) exitOnError("Writing to input buffer. (vert1_buf)"); status = clEnqueueWriteBuffer( commandQueue, vert2_buf, CL_TRUE, 0, sizeof(cl_double4) * entriesToWrite, vert2 + offset, 0, NULL, NULL); if(status != CL_SUCCESS) exitOnError("Writing to input buffer. (vert2_buf)"); status = clEnqueueWriteBuffer( commandQueue, vert3_buf, CL_TRUE, 0, sizeof(cl_double4) * entriesToWrite, vert3 + offset, 0, NULL, NULL); if(status != CL_SUCCESS) exitOnError("Writing to input buffer. (vert3_buf)"); }
//Create Input/Output buffers and assign them as kernel arguments void allocateBuffers(void) { bufferWidth = (paddedWidth <= WORK_ITEM_LIMIT) ? paddedWidth:WORK_ITEM_LIMIT; // Create OpenCL memory buffers //Input buffers orig_buf = clCreateBuffer( context, CL_MEM_READ_ONLY, sizeof(cl_double4) * bufferWidth, NULL, &status); if(status != CL_SUCCESS) exitOnError("Cannot Create buffer(orig)"); dir_buf = clCreateBuffer( context, CL_MEM_READ_ONLY, sizeof(cl_double4) * bufferWidth, NULL, &status); if(status != CL_SUCCESS) exitOnError("Cannot Create buffer(dir)"); vert0_buf = clCreateBuffer( context, CL_MEM_READ_ONLY, sizeof(cl_double4) * bufferWidth, NULL, &status); if(status != CL_SUCCESS) exitOnError("Cannot Create buffer(vert0)"); vert1_buf = clCreateBuffer( context, CL_MEM_READ_ONLY, sizeof(cl_double4) * bufferWidth, NULL, &status); if(status != CL_SUCCESS) exitOnError("Cannot Create buffer(vert1)"); vert2_buf = clCreateBuffer( context, CL_MEM_READ_ONLY, sizeof(cl_double4) * bufferWidth, NULL, &status); if(status != CL_SUCCESS) exitOnError("Cannot Create buffer(vert2)"); vert3_buf = clCreateBuffer( context, CL_MEM_READ_ONLY, sizeof(cl_double4) * bufferWidth, NULL, &status); if(status != CL_SUCCESS) exitOnError("Cannot Create buffer(vert3)"); //Output buffers cartesian_buf = clCreateBuffer( context, CL_MEM_WRITE_ONLY, sizeof(cl_double8) * bufferWidth, NULL, &status); if(status != CL_SUCCESS) exitOnError("Cannot Create buffer(cartesian_buf)"); barycentric_buf = clCreateBuffer( context, CL_MEM_WRITE_ONLY, sizeof(cl_double4) * bufferWidth, NULL, &status); if(status != CL_SUCCESS) exitOnError("Cannot Create buffer(barycentric_buf)"); parametric_buf = clCreateBuffer( context, CL_MEM_WRITE_ONLY, sizeof(cl_double2) * bufferWidth, NULL, &status); if(status != CL_SUCCESS) exitOnError("Cannot Create buffer(parametric_buf)"); //Assign the buffers as kernel arguments status = clSetKernelArg( kernel, 0, sizeof(cl_mem), (void *)&orig_buf); if(status != CL_SUCCESS) exitOnError("Setting kernel argument. (orig_buf)"); status = clSetKernelArg( kernel, 1, sizeof(cl_mem), (void *)&dir_buf); if(status != CL_SUCCESS) exitOnError("Setting kernel argument. (dir_buf)"); status = clSetKernelArg( kernel, 2, sizeof(cl_mem), (void *)&vert0_buf); if(status != CL_SUCCESS) exitOnError("Setting kernel argument. (vert0_buf)"); status = clSetKernelArg( kernel, 3, sizeof(cl_mem), (void *)&vert1_buf); if(status != CL_SUCCESS) exitOnError("Setting kernel argument. (vert1_buf)"); status = clSetKernelArg( kernel, 4, sizeof(cl_mem), (void *)&vert2_buf); if(status != CL_SUCCESS) exitOnError("Setting kernel argument. (vert2_buf)"); status = clSetKernelArg( kernel, 5, sizeof(cl_mem), (void *)&vert3_buf); if(status != CL_SUCCESS) exitOnError("Setting kernel argument. (vert3_buf)"); status = clSetKernelArg( kernel, 6, sizeof(cl_mem), (void *)&cartesian_buf); if(status != CL_SUCCESS) exitOnError("Setting kernel argument. (cartesian_buf)"); status = clSetKernelArg( kernel, 7, sizeof(cl_mem), (void *)&barycentric_buf); if(status != CL_SUCCESS) exitOnError("Setting kernel argument. (cartesian_buf)"); status = clSetKernelArg( kernel, 8, sizeof(cl_mem), (void *)¶metric_buf); if(status != CL_SUCCESS) exitOnError("Setting kernel argument. (cartesian_buf)"); }
//Determines the size of the input arrays needed and allocates them void allocateInput(int actual_width,int deviceNum) { //The size of the input arrays and buffers must be a multiple of the workgroup size if(threadsPerWorkgroup == 32) {//if this is an Nvidia GPU use the maximum workgroup size allowed by the kernel //Determine the maximum workgroup size allowed on the current device for this kernel. size_t maxGroupSize; status = clGetKernelWorkGroupInfo(kernel, devices[deviceNum], CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &maxGroupSize, NULL); if(status != CL_SUCCESS) exitOnError("Cannot get maximum workgroup size for given kernel.(clGetKernelWorkGroupInfo)\n"); threadsPerWorkgroup = maxGroupSize; //cout << "Work group size: " << maxGroupSize << endl; } //Determine the amount of false entries to pad the input arrays with. //Create a workgroup size of threadsPerWorkgroup if((actual_width % threadsPerWorkgroup) != 0) paddedWidth = actual_width + (threadsPerWorkgroup - (actual_width % threadsPerWorkgroup)); else paddedWidth = actual_width; //Memory used to store vector objects must be stored in 16 byte aligned addresses. //Mostly needed for 32bit systems. #if defined (_WIN32) //Input Arrays origin = (cl_double4 *) _aligned_malloc(paddedWidth * sizeof(cl_double4),16); if(origin == NULL) exitOnError("Failed to allocate input memory on host(origin)"); dir = (cl_double4 *) _aligned_malloc(paddedWidth * sizeof(cl_double4),16); if(dir == NULL) exitOnError("Failed to allocate input memory on host(dir)"); vert0 = (cl_double4 *) _aligned_malloc(paddedWidth * sizeof(cl_double4),16); if(vert0 == NULL) exitOnError("Failed to allocate input memory on host(vert0)"); vert1 = (cl_double4 *) _aligned_malloc(paddedWidth * sizeof(cl_double4),16); if(vert1 == NULL) exitOnError("Failed to allocate input memory on host(vert1)"); vert2 = (cl_double4 *) _aligned_malloc(paddedWidth * sizeof(cl_double4),16); if(vert2 == NULL) exitOnError("Failed to allocate input memory on host(vert2)"); vert3 = (cl_double4 *) _aligned_malloc(paddedWidth * sizeof(cl_double4),16); if(vert3 == NULL) exitOnError("Failed to allocate input memory on host(vert3)"); //Output Arrays cartesian = (cl_double8*)_aligned_malloc(paddedWidth * sizeof(cl_double8),16); if(cartesian == NULL) exitOnError("Failed to allocate output memory on host(cartesian)"); barycentric = (cl_double4*)_aligned_malloc(paddedWidth * sizeof(cl_double4),16); if(barycentric == NULL) exitOnError("Failed to allocate output memory on host(barycentric)"); parametric = (cl_double2*)_aligned_malloc(paddedWidth * sizeof(cl_double2),16); if(parametric == NULL) exitOnError("Failed to allocate output memory on host(parametric)"); #elif defined _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 //Input Arrays status = posix_memalign((void**)&origin,16,paddedWidth * sizeof(cl_double4)); if(status != 0) exitOnError("Failed to allocate input memory on host(origin)"); status = posix_memalign((void**)&dir,16,paddedWidth * sizeof(cl_double4)); if(status != 0) exitOnError("Failed to allocate input memory on host(dir)"); status = posix_memalign((void**)&vert0,16,paddedWidth * sizeof(cl_double4)); if(status != 0) exitOnError("Failed to allocate input memory on host(vert0)"); status = posix_memalign((void**)&vert1,16,paddedWidth * sizeof(cl_double4)); if(status != 0) exitOnError("Failed to allocate input memory on host(vert1)"); status = posix_memalign((void**)&vert2,16,paddedWidth * sizeof(cl_double4)); if(status != 0) exitOnError("Failed to allocate input memory on host(vert2)"); status = posix_memalign((void**)&vert3,16,paddedWidth * sizeof(cl_double4)); if(status != 0) exitOnError("Failed to allocate input memory on host(vert3)"); //Output Arrays status = posix_memalign((void**)&cartesian,16,paddedWidth * sizeof(cl_double8)); if(status != 0) exitOnError("Failed to allocate input memory on host(cartesian)"); status = posix_memalign((void**)&barycentric,16,paddedWidth * sizeof(cl_double4)); if(status != 0) exitOnError("Failed to allocate input memory on host(berycentric)"); status = posix_memalign((void**)¶metric,16,paddedWidth * sizeof(cl_double2)); if(status != 0) exitOnError("Failed to allocate input memory on host(parametric)"); #else origin = (cl_double4 *) malloc(paddedWidth * sizeof(cl_double4)); if(origin == NULL) exitOnError("Failed to allocate input memory on host(origin)"); dir = (cl_double4 *) malloc(paddedWidth * sizeof(cl_double4)); if(dir == NULL) exitOnError("Failed to allocate input memory on host(dir)"); vert0 = (cl_double4 *) malloc(paddedWidth * sizeof(cl_double4)); if(vert0 == NULL) exitOnError("Failed to allocate input memory on host(vert0)"); vert1 = (cl_double4 *) malloc(paddedWidth * sizeof(cl_double4)); if(vert1 == NULL) exitOnError("Failed to allocate input memory on host(vert1)"); vert2 = (cl_double4 *) malloc(paddedWidth * sizeof(cl_double4)); if(vert2 == NULL) exitOnError("Failed to allocate input memory on host(vert2)"); vert3 = (cl_double4 *) malloc(paddedWidth * sizeof(cl_double4)); if(vert3 == NULL) exitOnError("Failed to allocate input memory on host(vert3)"); //Output Arrays cartesian = (cl_double8*)malloc(paddedWidth * sizeof(cl_double8)); if(cartesian == NULL) exitOnError("Failed to allocate output memory on host(cartesian)"); barycentric = (cl_double4*)malloc(paddedWidth * sizeof(cl_double4)); if(barycentric == NULL) exitOnError("Failed to allocate output memory on host(barycentric)"); parametric = (cl_double2*)malloc(paddedWidth * sizeof(cl_double2)); if(parametric == NULL) exitOnError("Failed to allocate output memory on host(parametric)"); #endif }