int VMDinitialize(int *argc, char ***argv) { int i; #if defined VMDMPI // hack to fix up env vars if necessary for (i=0; i<(*argc); i++) { if(!strupcmp((*argv)[i], "-vmddir")) { if((*argc) > (i + 1)) { setenv("VMDDIR", (*argv)[++i], 1); } else { msgErr << "-vmddir must specify a fully qualified path." << sendmsg; } } } vmd_mpi_init(argc, argv); // initialize MPI, fix up env vars, etc. #endif #if defined(_MSC_VER) && !defined(VMDSEPARATESTARTUP) win32vmdstart(); // get registry info etc #endif #if !defined(VMDNOMACBUNDLE) && defined(__APPLE__) macosxvmdstart(*argc, *argv); // get env variables etc #endif // Tell Tcl where the executable is located const char *argv0 = vmd_initialize_tcl((*argv)[0]); #ifdef VMDTCL // register signal handler tclhandler = Tcl_AsyncCreate(VMDTclAsyncProc, (ClientData)NULL); signal(SIGINT, (sighandler_t) VMDTclSigHandler); #endif // Let people know who we are. VMDtitle(); // Tell the user what we think about the hardware we're running on. // If VMD is compiled for MPI, then we don't print any of the normal // standalone startup messages and instead we use the special MPI-specific // node scan startup messages only. #if !defined(VMDMPI) #if defined(VMDTHREADS) int vmdnumcpus = wkf_thread_numprocessors(); msgInfo << "Multithreading available, " << vmdnumcpus << ((vmdnumcpus > 1) ? " CPUs" : " CPU") << " detected." << sendmsg; #endif long vmdcorefree = vmd_get_avail_physmem_mb(); if (vmdcorefree >= 0) { long vmdcorepcnt = vmd_get_avail_physmem_percent(); msgInfo << "Free system memory: " << vmdcorefree << "MB (" << vmdcorepcnt << "%)" << sendmsg; } #endif // Read environment variables and command line options. // Initialize customArgv with just argv0 to avoid problems with // Tcl extension. customArgv.append((char *)argv0); VMDGetOptions(*argc, *argv); #if (!defined(__APPLE__) && !defined(_MSC_VER)) && (defined(VMDOPENGL) || defined(VMDFLTK)) // If we're using X-windows, we autodetect if the DISPLAY environment // variable is unset, and automatically switch back to text mode without // requiring the user to pass the "-dispdev text" command line parameters if ((which_display == DISPLAY_WIN) && (getenv("DISPLAY") == NULL)) { which_display = DISPLAY_TEXT; } #endif #if defined(VMDTKCON) vmdcon_init(); msgInfo << "Using VMD Console redirection interface." << sendmsg; // we default to a widget mode console, unless text mode is requested. // we don't have an tcl interpreter registered yet, so it is set to NULL. // flushing pending messages to the screen, is only in text mode possible. if ((which_display == DISPLAY_TEXT) || just_print_help) { vmdcon_use_text(NULL); vmdcon_purge(); } else { vmdcon_use_widget(NULL); } #endif #ifdef VMDFLTK // Do various special FLTK initialization stuff here if ((which_display != DISPLAY_TEXT)) { // Cause FLTK to to use 24-bit color for all windows if possible // This must be done before any FLTK windows are shown for the first time. if (!Fl::visual(FL_DOUBLE | FL_RGB8)) { if (!Fl::visual(FL_RGB8)) { Fl::visual(FL_RGB); } } // Disable the use of the arrow keys for navigating buttons and other // non-text widgets, we'll try it out and see how it pans out Fl::visible_focus(0); // Disable Drag 'n Drop since the only text field in VMD is the // atomselection input and DND severely gets in the way there. Fl::dnd_text_ops(0); } #endif // Quit now if the user just wanted a list of command line options. if (just_print_help) { vmd_sleep(10); // This is here so that the user can see the message // before the terminal/shell exits... return 0; } // Set up default allocators; these may be overridden by cave or freevr. vmd_alloc = malloc; // system malloc() in the default case vmd_dealloc = free; // system free() in the default case vmd_realloc = realloc; // system realloc(), set to NULL when not available // check for a CAVE display if (DISPLAY_USES_CAVE(which_display)) { #ifdef VMDCAVE // allocate shared memory pool used to communicate with child renderers int megs = 2048; if (getenv("VMDCAVEMEM") != NULL) { megs = atoi(getenv("VMDCAVEMEM")); } msgInfo << "Attempting to get " << megs << "MB of CAVE Shared Memory" << sendmsg; grab_CAVE_memory(megs); CAVEConfigure(argc, *argv, NULL); // configure cave walls and memory use // point VMD shared memory allocators to CAVE routines vmd_alloc = malloc_from_CAVE_memory; vmd_dealloc = free_to_CAVE_memory; vmd_realloc = NULL; // no realloc() functionality is available presently #else msgErr << "Not compiled with the CAVE options set." << sendmsg; which_display = DISPLAY_WIN; #endif } // check for a FreeVR display if (DISPLAY_USES_FREEVR(which_display)) { #ifdef VMDFREEVR int megs = 2048; if (getenv("VMDFREEVRMEM") != NULL) { megs = atoi(getenv("VMDFREEVRMEM")); } msgInfo << "Attempting to get " << megs << "MB of FreeVR Shared Memory" << sendmsg; grab_FreeVR_memory(megs); // have to do this *before* vrConfigure() if // we want more than the default shared mem. vrConfigure(NULL, NULL, NULL); // configure FreeVR walls // point shared memory allocators to FreeVR routines vmd_alloc = malloc_from_FreeVR_memory; vmd_dealloc = free_to_FreeVR_memory; vmd_realloc = NULL; // no realloc() functionality is available presently #else msgErr << "Not compiled with the FREEVR options set." << sendmsg; which_display = DISPLAY_WIN; #endif } // return custom argc/argv *argc = customArgv.num(); for (i=0; i<customArgv.num(); i++) { (*argv)[i] = customArgv[i]; } return 1; // successful startup }
static int vmd_gaussdensity_threaded(int natoms, const float *xyzr, const float *colors, float *densitymap, float *voltexmap, const int *numvoxels, float radscale, float gridspacing, float isovalue, float gausslim) { densitythrparms parms; memset(&parms, 0, sizeof(parms)); parms.natoms = natoms; parms.radscale = radscale; parms.gridspacing = gridspacing; parms.isovalue = isovalue; parms.gausslim = gausslim; parms.numvoxels = numvoxels; parms.xyzr = xyzr; parms.colors = colors; int physprocs = wkf_thread_numprocessors(); int maxprocs = physprocs; // We can productively use only a few cores per socket due to the // limited memory bandwidth per socket. Also, hyperthreading // actually hurts performance. These two considerations combined // with the linear increase in memory use prevent us from using large // numbers of cores with this simple approach, so if we've got more // than 8 CPU cores, we'll iteratively cutting the core count in // half until we're under 8 cores. while (maxprocs > 8) maxprocs /= 2; // Limit the number of CPU cores used so we don't run the // machine out of memory during surface computation. // For now we'll set a practical maximum memory use limit to // 2GB total for all cores. long volsz = numvoxels[0] * numvoxels[1] * numvoxels[2]; long volmemsz = sizeof(float) * volsz; long volmemszkb = volmemsz / 1024; long volmemtexszkb = (volmemszkb + (voltexmap != NULL) ? 3*volmemszkb : 0); #if defined(ARCH_BLUEWATERS) while ((volmemtexszkb * maxprocs) > (4 * 1024 * 1024)) maxprocs /= 2; #else while ((volmemtexszkb * maxprocs) > (2 * 1024 * 1024)) maxprocs /= 2; #endif if (maxprocs < 1) maxprocs = 1; // Loop over number of physical processors and try to create // per-thread volumetric maps for each of them. parms.thrdensitymaps = (float **) calloc(1,maxprocs * sizeof(float *)); parms.thrvoltexmaps = (float **) calloc(1, maxprocs * sizeof(float *)); // first thread is already ready to go parms.thrdensitymaps[0] = densitymap; parms.thrvoltexmaps[0] = voltexmap; int i; int numprocs = maxprocs; // ever the optimist for (i=1; i<maxprocs; i++) { parms.thrdensitymaps[i] = (float *) calloc(1, volmemsz); if (parms.thrdensitymaps[i] == NULL) { numprocs = i; break; } if (voltexmap != NULL) { parms.thrvoltexmaps[i] = (float *) calloc(1, 3 * volmemsz); if (parms.thrvoltexmaps[i] == NULL) { free(parms.thrdensitymaps[i]); parms.thrdensitymaps[i] = NULL; numprocs = i; break; } } } // launch independent thread calculations wkf_tasktile_t tile; tile.start = 0; tile.end = natoms; wkf_threadlaunch(numprocs, &parms, densitythread, &tile); // do a parallel reduction of the resulting density maps tile.start = 0; tile.end = volsz; wkf_threadlaunch(numprocs, &parms, reductionthread, &tile); // free work area for (i=1; i<maxprocs; i++) { if (parms.thrdensitymaps[i] != NULL) free(parms.thrdensitymaps[i]); if (parms.thrvoltexmaps[i] != NULL) free(parms.thrvoltexmaps[i]); } free(parms.thrdensitymaps); free(parms.thrvoltexmaps); return 0; }