// return a string describing an app version // static void app_version_desc(BEST_APP_VERSION& bav, char* buf) { if (!bav.present) { strcpy(buf, "none"); return; } if (bav.cavp) { sprintf(buf, "anonymous platform (%s)", proc_type_name(bav.host_usage.proc_type)); } else { sprintf(buf, "[AV#%lu]", bav.avp->id); } }
// Either appName argument or projName argument may be NULL void CSimpleTaskPanel::GetApplicationAndProjectNames(RESULT* result, wxString* appName, wxString* projName) { CMainDocument* pDoc = wxGetApp().GetDocument(); RESULT* state_result = NULL; wxString strAppBuffer = wxEmptyString; wxString strGPUBuffer = wxEmptyString; wxString pct_done_str = wxEmptyString; wxASSERT(pDoc); wxASSERT(wxDynamicCast(pDoc, CMainDocument)); state_result = pDoc->state.lookup_result(result->project_url, result->name); if (!state_result) { pDoc->ForceCacheUpdate(); state_result = pDoc->state.lookup_result(result->project_url, result->name); } if (!state_result) return; if (appName != NULL) { WORKUNIT* wup = state_result->wup; if (!wup) return; APP* app = wup->app; if (!app) return; APP_VERSION* avp = state_result->avp; if (!avp) return; if (strlen(app->user_friendly_name)) { strAppBuffer = wxString(state_result->app->user_friendly_name, wxConvUTF8); } else { strAppBuffer = wxString(state_result->avp->app_name, wxConvUTF8); } char buf[256]; if (avp->gpu_type) { sprintf(buf, " (%s)", proc_type_name(avp->gpu_type)); strGPUBuffer = wxString(buf, wxConvUTF8); } appName->Printf( wxT("%s%s%s"), state_result->project->anonymous_platform?_("Local: "):wxT(""), strAppBuffer.c_str(), strGPUBuffer.c_str() ); } if (projName != NULL) { *projName = wxString(state_result->project->project_name.c_str(), wxConvUTF8 ); if (projName->IsEmpty()) { *projName = _("Not Available"); } } }
// for new-style requests, check that the app version uses a // resource for which we need work // bool need_this_resource( HOST_USAGE& host_usage, APP_VERSION* avp, CLIENT_APP_VERSION* cavp ) { if (!g_wreq->rsc_spec_request) { return true; } int pt = host_usage.proc_type; if (!g_wreq->need_proc_type(pt)) { dont_need_message(proc_type_name(pt), avp, cavp); return false; } return true; }
void html_device_header() { fprintf(html_out, "<tr>" " <td valign=top>%s</td>" " <th>CPU</th>", sim_time_string(gstate.now) ); for (int i=1; i<coprocs.n_rsc; i++) { int pt = coproc_type_name_to_num(coprocs.coprocs[i].type); const char* name; if (pt) { name = proc_type_name(pt); } else { name = coprocs.coprocs[i].type; } fprintf(html_out, "<th>%s</th>\n", name); } fprintf(html_out, "</tr>\n" ); }
// return the app version with greatest projected FLOPS // for the given job and host, or NULL if none is available // // NOTE: the BEST_APP_VERSION structure returned by this // must not be modified or reused; // a pointer to it is stored in APP_VERSION. // // check_req: if set, return only app versions that use resources // for which the work request is nonzero. // This check is not done for: // - assigned jobs // - resent jobs // reliable_only: use only versions for which this host is "reliable" // // We "memoize" the results, maintaining an array g_wreq->best_app_versions // that maps app ID to the best app version (or NULL). // BEST_APP_VERSION* get_app_version( WORKUNIT& wu, bool check_req, bool reliable_only ) { unsigned int i; int j; BEST_APP_VERSION* bavp; char buf[256]; bool job_needs_64b = (wu.rsc_memory_bound > max_32b_address_space()); if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] get_app_version(): getting app version for WU#%lu (%s) appid:%lu\n", wu.id, wu.name, wu.appid ); if (job_needs_64b) { log_messages.printf(MSG_NORMAL, "[version] job needs 64-bit app version: mem bnd %f\n", wu.rsc_memory_bound ); } } APP* app = ssp->lookup_app(wu.appid); if (!app) { log_messages.printf(MSG_CRITICAL, "WU refers to nonexistent app: %lu\n", wu.appid ); return NULL; } // if the app uses homogeneous app version, // don't send to anonymous platform client. // Then check if the WU is already committed to an app version // if (app->homogeneous_app_version) { if (g_wreq->anonymous_platform) { return NULL; } if ( wu.app_version_id) { return check_homogeneous_app_version(wu, reliable_only); } } // see if app is already in memoized array // std::vector<BEST_APP_VERSION*>::iterator bavi; bavi = g_wreq->best_app_versions.begin(); while (bavi != g_wreq->best_app_versions.end()) { bavp = *bavi; if (bavp->appid == wu.appid && (job_needs_64b == bavp->for_64b_jobs)) { if (!bavp->present) { #if 0 if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] returning cached NULL\n" ); } #endif return NULL; } // if we're at the jobs-in-progress limit for this // app and resource type, fall through and find another version // if (config.max_jobs_in_progress.exceeded( app, bavp->host_usage.proc_type )) { if (config.debug_version_select) { app_version_desc(*bavp, buf); log_messages.printf(MSG_NORMAL, "[version] %s: max jobs in progress exceeded\n", buf ); } g_wreq->best_app_versions.erase(bavi); break; } // if we previously chose an app version but don't need more work // for that processor type, fall through and find another version // if (check_req && g_wreq->rsc_spec_request) { int pt = bavp->host_usage.proc_type; if (!g_wreq->need_proc_type(pt)) { if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] have %s version but no more %s work needed\n", proc_type_name(pt), proc_type_name(pt) ); } g_wreq->best_app_versions.erase(bavi); break; } } if (config.debug_version_select) { app_version_desc(*bavp, buf); log_messages.printf(MSG_NORMAL, "[version] returning cached version: %s\n", buf ); } return bavp; } ++bavi; } // here if app was not in memoized array, // or we couldn't use the app version there. if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] looking for version of %s\n", app->name ); } bavp = new BEST_APP_VERSION; bavp->appid = wu.appid; bavp->for_64b_jobs = job_needs_64b; if (g_wreq->anonymous_platform) { CLIENT_APP_VERSION* cavp = get_app_version_anonymous( *app, job_needs_64b, reliable_only ); if (!cavp) { bavp->present = false; } else { bavp->present = true; bavp->host_usage = cavp->host_usage; bavp->cavp = cavp; int gavid = host_usage_to_gavid(cavp->host_usage, *app); bavp->reliable = app_version_is_reliable(gavid); bavp->trusted = app_version_is_trusted(gavid); if (config.debug_version_select) { app_version_desc(*bavp, buf); log_messages.printf(MSG_NORMAL, "[version] using %s\n", buf); } } g_wreq->best_app_versions.push_back(bavp); if (!bavp->present) return NULL; return bavp; } // Go through the client's platforms, // and scan the app versions for each platform. // Pick the one with highest expected FLOPS // // if config.prefer_primary_platform is set: // stop scanning platforms once we find a feasible version bavp->host_usage.projected_flops = 0; bavp->avp = NULL; for (i=0; i<g_request->platforms.list.size(); i++) { bool found_feasible_version = false; PLATFORM* p = g_request->platforms.list[i]; if (job_needs_64b && !is_64b_platform(p->name)) { continue; } for (j=0; j<ssp->napp_versions; j++) { HOST_USAGE host_usage; APP_VERSION& av = ssp->app_versions[j]; if (av.appid != wu.appid) continue; if (av.platformid != p->id) continue; if (av.beta) { if (!g_wreq->allow_beta_work) { continue; } } if (strlen(av.plan_class)) { if (!app_plan(*g_request, av.plan_class, host_usage)) { if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] [AV#%lu] app_plan() returned false\n", av.id ); } continue; } if (!g_request->client_cap_plan_class) { if (!host_usage.is_sequential_app()) { if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] [AV#%lu] client %d lacks plan class capability\n", av.id, g_request->core_client_version ); } continue; } } } else { host_usage.sequential_app(g_reply->host.p_fpops); } // skip versions that go against resource prefs // int pt = host_usage.proc_type; if (g_wreq->dont_use_proc_type[pt]) { if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] [AV#%lu] Skipping %s version - user prefs say no %s\n", av.id, proc_type_name(pt), proc_type_name(pt) ); } continue; } if (reliable_only && !app_version_is_reliable(av.id)) { if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] [AV#%lu] not reliable\n", av.id ); } continue; } if (daily_quota_exceeded(av.id, host_usage)) { if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] [AV#%lu] daily quota exceeded\n", av.id ); } continue; } // skip versions for which we're at the jobs-in-progress limit // if (config.max_jobs_in_progress.exceeded(app, host_usage.proc_type)) { if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] [AV#%lu] jobs in progress limit exceeded\n", av.id ); config.max_jobs_in_progress.print_log(); } continue; } // skip versions for resources we don't need // if (check_req && !need_this_resource(host_usage, &av, NULL)) { continue; } // skip versions which require a newer core client // if (g_request->core_client_version < av.min_core_version) { if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] [AV#%lu] client version %d < min core version %d\n", av.id, g_request->core_client_version, av.min_core_version ); } // Do not tell the user he needs to update the client // just because the client is too old for a particular app version // g_wreq->outdated_client = true; continue; } if (av.max_core_version && g_request->core_client_version > av.max_core_version) { if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] [AV#%lu] client version %d > max core version %d\n", av.id, g_request->core_client_version, av.max_core_version ); } continue; } // at this point we know the version is feasible, // so if config.prefer_primary_platform is set // we won't look any further. // found_feasible_version = true; // pick the fastest version. // Throw in a random factor in case the estimates are off. // DB_HOST_APP_VERSION* havp = gavid_to_havp(av.id); double r = 1; long n = 1; if (havp) { // slowly move from raw calc to measured performance as number // of results increases // n = std::max((long)havp->pfc.n, (long)n); double old_projected_flops = host_usage.projected_flops; estimate_flops(host_usage, av); host_usage.projected_flops = (host_usage.projected_flops*(n-1) + old_projected_flops)/n; // special case for versions that don't work on a given host. // This is defined as: // 1. pfc.n is 0 // 2. The max_jobs_per_day is 1 // 3. Consecutive valid is 0. // In that case, heavily penalize this app_version most of the // time. // if ((havp->pfc.n==0) && (havp->max_jobs_per_day==1) && (havp->consecutive_valid==0)) { if (drand() > 0.01) { host_usage.projected_flops *= 0.01; if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] App version AV#%lu is failing on HOST#%lu\n", havp->app_version_id, havp->host_id ); } } } } if (config.version_select_random_factor) { r += config.version_select_random_factor*rand_normal()/n; if (r <= .1) { r = .1; } } if (config.debug_version_select && bavp && bavp->avp) { log_messages.printf(MSG_NORMAL, "[version] Comparing AV#%lu (%.2f GFLOP) against AV#%lu (%.2f GFLOP)\n", av.id, host_usage.projected_flops/1e+9, bavp->avp->id, bavp->host_usage.projected_flops/1e+9 ); } if (r*host_usage.projected_flops > bavp->host_usage.projected_flops) { if (config.debug_version_select && (host_usage.projected_flops <= bavp->host_usage.projected_flops)) { log_messages.printf(MSG_NORMAL, "[version] [AV#%lu] Random factor wins. r=%f n=%ld\n", av.id, r, n ); } host_usage.projected_flops*=r; bavp->host_usage = host_usage; bavp->avp = &av; bavp->reliable = app_version_is_reliable(av.id); bavp->trusted = app_version_is_trusted(av.id); if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] Best app version is now AV%lu (%.2f GFLOP)\n", bavp->avp->id, bavp->host_usage.projected_flops/1e+9 ); } } else { if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] Not selected, AV#%lu r*%.2f GFLOP <= Best AV %.2f GFLOP (r=%f, n=%ld)\n", av.id, host_usage.projected_flops/1e+9, bavp->host_usage.projected_flops/1e+9, r, n ); } } } // loop over app versions if (config.prefer_primary_platform && found_feasible_version) { break; } } // loop over client platforms if (bavp->avp) { estimate_flops(bavp->host_usage, *bavp->avp); if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] Best version of app %s is [AV#%lu] (%.2f GFLOPS)\n", app->name, bavp->avp->id, bavp->host_usage.projected_flops/1e9 ); } bavp->present = true; g_wreq->best_app_versions.push_back(bavp); } else { // Here if there's no app version we can use. // if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] returning NULL; platforms:\n" ); for (i=0; i<g_request->platforms.list.size(); i++) { PLATFORM* p = g_request->platforms.list[i]; log_messages.printf(MSG_NORMAL, "[version] %s\n", p->name ); } } g_wreq->best_app_versions.push_back(bavp); return NULL; } return bavp; }
// show project properties // void CDlgItemProperties::renderInfos(PROJECT* project_in) { std::string projectname; //collecting infos project_in->get_name(projectname); //disk usage needs additional lookups CMainDocument* pDoc = wxGetApp().GetDocument(); pDoc->CachedDiskUsageUpdate(); // CachedDiskUsageUpdate() may have invalidated our project // pointer, so get an updated pointer to this project PROJECT* project = pDoc->project(project_in->master_url); if (!project) return; // TODO: display some sort of error alert? std::vector<PROJECT*> dp = pDoc->disk_usage.projects; double diskusage=0.0; for (unsigned int i=0; i< dp.size(); i++) { PROJECT* tp = dp[i]; std::string tname; tp->get_name(tname); wxString t1(wxString(tname.c_str(), wxConvUTF8)); if(t1.IsSameAs(wxString(projectname.c_str(), wxConvUTF8)) || t1.IsSameAs(wxString(project->master_url, wxConvUTF8))) { diskusage = tp->disk_usage; break; } } //set dialog title wxString wxTitle = _("Properties of project "); wxTitle.append(wxString(projectname.c_str(),wxConvUTF8)); SetTitle(wxTitle); //layout controls addSection(_("General")); addProperty(_("Master URL"), wxString(project->master_url, wxConvUTF8)); addProperty(_("User name"), wxString(project->user_name.c_str(), wxConvUTF8)); addProperty(_("Team name"), wxString(project->team_name.c_str(), wxConvUTF8)); addProperty(_("Resource share"), wxString::Format(wxT("%0.0f"), project->resource_share)); if (project->min_rpc_time > dtime()) { addProperty(_("Scheduler RPC deferred for"), FormatTime(project->min_rpc_time - dtime())); } if (project->download_backoff) { addProperty(_("File downloads deferred for"), FormatTime(project->download_backoff)); } if (project->upload_backoff) { addProperty(_("File uploads deferred for"), FormatTime(project->upload_backoff)); } addProperty(_("Disk usage"), FormatDiskSpace(diskusage)); addProperty(_("Computer ID"), wxString::Format(wxT("%d"), project->hostid)); if (project->non_cpu_intensive) { addProperty(_("Non CPU intensive"), _("yes")); } addProperty(_("Suspended via GUI"), project->suspended_via_gui ? _("yes") : _("no")); addProperty(_("Don't request more work"), project->dont_request_more_work ? _("yes") : _("no")); if (project->scheduler_rpc_in_progress) { addProperty(_("Scheduler call in progress"), _("yes")); } if (project->trickle_up_pending) { addProperty(_("Trickle-up pending"), _("yes")); } if (strlen(project->venue)) { addProperty(_("Host location"), wxString(project->venue, wxConvUTF8)); } else { addProperty(_("Host location"), _("default")); } if (project->attached_via_acct_mgr) { addProperty(_("Added via account manager"), _("yes")); } if (project->detach_when_done) { addProperty(_("Remove when tasks done"), _("yes")); } if (project->ended) { addProperty(_("Ended"), _("yes")); } addProperty(_("Tasks completed"), wxString::Format(wxT("%d"), project->njobs_success)); addProperty(_("Tasks failed"), wxString::Format(wxT("%d"), project->njobs_error)); addSection(_("Credit")); addProperty(_("User"), wxString::Format( wxT("%0.2f total, %0.2f average"), project->user_total_credit, project->user_expavg_credit ) ); addProperty(_("Host"), wxString::Format( wxT("%0.2f total, %0.2f average"), project->host_total_credit, project->host_expavg_credit ) ); if (!project->non_cpu_intensive) { addSection(_("Scheduling")); addProperty(_("Scheduling priority"), wxString::Format(wxT("%0.2f"), project->sched_priority)); show_rsc(_("CPU"), project->rsc_desc_cpu); if (pDoc->state.host_info.coprocs.have_nvidia()) { show_rsc( wxString(proc_type_name(PROC_TYPE_NVIDIA_GPU), wxConvUTF8), project->rsc_desc_nvidia ); } if (pDoc->state.host_info.coprocs.have_ati()) { show_rsc( wxString(proc_type_name(PROC_TYPE_AMD_GPU), wxConvUTF8), project->rsc_desc_ati ); } if (pDoc->state.host_info.coprocs.have_intel_gpu()) { show_rsc( wxString(proc_type_name(PROC_TYPE_INTEL_GPU), wxConvUTF8), project->rsc_desc_intel_gpu ); } double dcf = project->duration_correction_factor; // if it's exactly 1, it's not being used // if (dcf != 1) { addProperty( _("Duration correction factor"), wxString::Format(wxT("%0.4f"), dcf) ); } } m_gbSizer->Layout(); m_scrolledWindow->FitInside(); }
// send work for a particular processor type // void send_work_score_type(int rt) { vector<JOB> jobs; if (config.debug_send) { log_messages.printf(MSG_NORMAL, "[send] scanning for %s jobs\n", proc_type_name(rt) ); } clear_others(rt); int nscan = config.mm_max_slots; if (!nscan) nscan = ssp->max_wu_results; int rnd_off = rand() % ssp->max_wu_results; for (int j=0; j<nscan; j++) { int i = (j+rnd_off) % ssp->max_wu_results; WU_RESULT& wu_result = ssp->wu_results[i]; if (wu_result.state != WR_STATE_PRESENT) { continue; } WORKUNIT wu = wu_result.workunit; JOB job; job.app = ssp->lookup_app(wu.appid); if (job.app->non_cpu_intensive) continue; job.bavp = get_app_version(wu, true, false); if (!job.bavp) continue; job.index = i; job.result_id = wu_result.resultid; if (!job.get_score(wu_result)) { continue; } jobs.push_back(job); } std::sort(jobs.begin(), jobs.end(), job_compare); bool sema_locked = false; for (unsigned int i=0; i<jobs.size(); i++) { if (!work_needed(false)) { break; } if (!g_wreq->need_proc_type(rt)) { break; } JOB& job = jobs[i]; if (!sema_locked) { lock_sema(); sema_locked = true; } // make sure the job is still in the cache // array is locked at this point. // WU_RESULT& wu_result = ssp->wu_results[job.index]; if (wu_result.state != WR_STATE_PRESENT) { continue; } if (wu_result.resultid != job.result_id) { continue; } WORKUNIT wu = wu_result.workunit; int retval = wu_is_infeasible_fast( wu, wu_result.res_server_state, wu_result.res_priority, wu_result.res_report_deadline, *job.app, *job.bavp ); if (retval) { continue; } wu_result.state = g_pid; // It passed fast checks. // Release sema and do slow checks // unlock_sema(); sema_locked = false; switch (slow_check(wu_result, job.app, job.bavp)) { case 1: wu_result.state = WR_STATE_PRESENT; break; case 2: wu_result.state = WR_STATE_EMPTY; break; default: // slow_check() refreshes fields of wu_result.workunit; // update our copy too // wu.hr_class = wu_result.workunit.hr_class; wu.app_version_id = wu_result.workunit.app_version_id; // mark slot as empty AFTER we've copied out of it // (since otherwise feeder might overwrite it) // wu_result.state = WR_STATE_EMPTY; // reread result from DB, make sure it's still unsent // TODO: from here to end of add_result_to_reply() // (which updates the DB record) should be a transaction // SCHED_DB_RESULT result; result.id = wu_result.resultid; if (result_still_sendable(result, wu)) { add_result_to_reply(result, wu, job.bavp, false); // add_result_to_reply() fails only in pathological cases - // e.g. we couldn't update the DB record or modify XML fields. // If this happens, don't replace the record in the array // (we can't anyway, since we marked the entry as "empty"). // The feeder will eventually pick it up again, // and hopefully the problem won't happen twice. } break; } } if (sema_locked) { unlock_sema(); } restore_others(rt); g_wreq->best_app_versions.clear(); }