/* * init_opencl_devices_and_shmem * * We can have performance gain using asynchronous DMA transfer when data * chunk it moved to OpenCL device from host machine, however, it requires * preparations to ensure the memory region to be copied to/from is pinned * on RAM; not swapped out. OpenCL provides an interface to map a certain * host address area as pinned buffer object, even though its size is * restricted to CL_DEVICE_MAX_MEM_ALLOC_SIZE parameter. Usually, it is * much less than size of shared memory to be assigned to PG-Strom, around * 500MB - 2GB in typical GPU/MIC device. So, we need to split a flat * continuous memory into several 'zones' to pin it using OpenCL interface. * Because it is a job of OpenCL intermediation server to collect properties * of devices, and this server shall be launched post initialization stage, * we also have to acquire and pin the shared memory region in the context * of OpenCL intermediation server, not postmaster itself. */ static void init_opencl_devices_and_shmem(void) { Size zone_length = LONG_MAX; List *devList; ListCell *cell; devList = construct_opencl_device_info(opencl_platform_index); if (devList == NIL) elog(ERROR, "PG-Strom: unavailable to use any OpenCL devices"); foreach (cell, devList) { pgstrom_device_info *dev_info = lfirst(cell); if (zone_length > dev_info->dev_max_mem_alloc_size) zone_length = dev_info->dev_max_mem_alloc_size; }
/* * pgstrom_opencl_main * * Main routine of opencl intermediation server. * * TODO: enhancement to use multi-threaded message handler. */ static void pgstrom_opencl_main(Datum main_arg) { pthread_t *threads; int i; /* mark this process is OpenCL intermediator */ pgstrom_i_am_clserv = true; /* * Set up signal handlers. Currently, OpenCL Server does not pay * attention on reloading of postgresql.conf, so we can ignore SIGHUP. */ pqsignal(SIGHUP, SIG_IGN); pqsignal(SIGTERM, pgstrom_opencl_sigterm); /* We're now ready to receive signals */ BackgroundWorkerUnblockSignals(); /* collect opencl platform/device info */ construct_opencl_device_info(); /* initialize opencl context and shared memory segment */ init_opencl_context_and_shmem(); elog(LOG, "Starting PG-Strom OpenCL Server"); /* * OK, ready to launch server thread. In the default, it creates * same number with online CPUs, but user can give an explicit * number using "pg_strom.opencl_num_threads" parameter. * * NOTE: sysconf(_SC_NPROCESSORS_ONLN) may not be portable. */ if (opencl_num_threads == 0) opencl_num_threads = sysconf(_SC_NPROCESSORS_ONLN); Assert(opencl_num_threads > 0); threads = malloc(sizeof(pthread_t) * opencl_num_threads); if (!threads) { elog(LOG, "out of memory"); return; } for (i=0; i < opencl_num_threads; i++) { if (pthread_create(&threads[i], NULL, pgstrom_opencl_event_loop, NULL) != 0) break; } /* * In case of any failure during pthread_create(), worker threads * will be terminated soon, then we can wait for thread joining. */ if (i < opencl_num_threads) { elog(LOG, "failed to create server threads"); pgstrom_clserv_exit_pending = true; pgstrom_cancel_server_loop(); } else elog(LOG, "PG-Strom: %d of server threads are up", opencl_num_threads); while (--i >= 0) pthread_join(threads[i], NULL); /* got a signal to stop background worker process */ elog(LOG, "Stopping PG-Strom OpenCL Server"); /* * close the server queue and returns unprocessed message with error. * * XXX - here is possible bug if server got signals during program * building; that holds some messages and callback enqueues * the messages again. */ pgstrom_close_server_queue(); }