12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319 |
- /*
- * nvbio
- * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the NVIDIA CORPORATION nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include <nvBowtie/bowtie2/cuda/stats.h>
- #include <nvbio/basic/html.h>
- #include <nvbio/io/alignments.h>
- #include <functional>
- #include <algorithm>
- #include <numeric>
- #ifndef WIN32
- #include <string>
- #endif
- namespace nvbio {
- namespace bowtie2 {
- namespace cuda {
- void generate_kernel_table(const uint32 id, const char* report, const KernelStats& stats);
- Stats::Stats(const Params _params) :
- n_reads(0),
- params( _params )
- {
- global_time = 0.0f;
- hits_total = 0u;
- hits_ranges = 0u;
- hits_max = 0u;
- hits_max_range = 0u;
- hits_top_total = 0u;
- hits_top_max = 0u;
- hits_stats = 0u;
- for (uint32 i = 0; i < 28; ++i)
- hits_bins[i] = hits_top_bins[i] = 0;
- map.name = "map"; map.units = "reads";
- select.name = "select"; select.units = "seeds";
- sort.name = "sort"; sort.units = "seeds";
- locate.name = "locate"; locate.units = "seeds";
- score.name = "score"; score.units = "seeds";
- opposite_score.name = "score-opposite"; opposite_score.units = "seeds";
- backtrack.name = "backtrack"; backtrack.units = "reads";
- backtrack_opposite.name = "backtrack-opposite"; backtrack_opposite.units = "reads";
- finalize.name = "finalize"; finalize.units = "reads";
- alignments_DtoH.name = "alignments-DtoH"; alignments_DtoH.units = "reads";
- read_HtoD.name = "reads-HtoD"; read_HtoD.units = "reads";
- read_io.name = "reads-IO"; read_io.units = "reads";
- io.name = "IO"; io.units = "reads";
- opposite_score.user_names[0] = "queue::get utilization"; opposite_score.user_avg[0] = true;
- opposite_score.user_names[1] = "queue::run utilization"; opposite_score.user_avg[1] = true;
- opposite_score.user_names[2] = "queue::run T_avg"; opposite_score.user_avg[2] = true;
- opposite_score.user_names[3] = "queue::run T_sigma"; opposite_score.user_avg[3] = false;
- }
- void Stats::track_alignment_statistics(
- const io::BestAlignments& alignment1,
- const io::BestAlignments& alignment2,
- const uint8 mapq)
- {
- n_reads++;
- const uint32 log_mapq = mapq ? nvbio::log2(mapq) + 1u : 0u;
- if (alignment1.best().is_concordant())
- {
- // keep track of mapping quality histogram
- concordant.mapq_bins[mapq]++;
- concordant.mapq_log_bins[log_mapq]++;
- // count this read as mapped
- concordant.n_mapped++;
- if (!alignment1.second_best().is_paired())
- {
- // we only have one score; count as a unique alignment
- concordant.n_unique++;
- }
- else
- {
- // we have two best scores, which implies two (or more) alignment positions
- // count as multiple alignment
- concordant.n_multiple++;
- }
- // compute final alignment score
- const int32 first = alignment1.best().score() + alignment2.best().score();
- const int32 second = alignment1.second_best().is_paired() ?
- alignment1.second_best().score() + alignment2.second_best().score() :
- Field_traits<int32>::min();
- // if the two best scores are equal, count as ambiguous
- if (first == second)
- concordant.n_ambiguous++;
- else {
- // else, the first score must be higher...
- NVBIO_CUDA_ASSERT(first > second);
- /// ... which counts as a nonambiguous alignment
- concordant.n_unambiguous++;
- }
- // compute edit distance scores
- const uint32 first_ed = alignment1.best().ed() + alignment2.best().ed();
- const uint32 second_ed = alignment1.second_best().is_paired() ?
- alignment1.second_best().ed() + alignment2.second_best().ed() : 255u;
- // update best edit-distance histograms
- if (first_ed < concordant.mapped_ed_histogram.size())
- {
- concordant.mapped_ed_histogram[first_ed]++;
- if (alignment1.best().is_rc())
- concordant.mapped_ed_histogram_fwd[first_ed]++;
- else
- concordant.mapped_ed_histogram_rev[first_ed]++;
- const uint32 log_first_ed = first_ed ? nvbio::log2(first_ed) + 1 : 0;
- concordant.mapped_log_ed_histogram[log_first_ed]++;
- }
- // track edit-distance correlation
- if (first_ed + 1 < 64)
- {
- if (second_ed + 1 < 64)
- concordant.mapped_ed_correlation[first_ed + 1][second_ed + 1]++;
- else
- concordant.mapped_ed_correlation[first_ed + 1][0]++;
- }
- }
- else if (alignment1.best().is_discordant())
- {
- // keep track of mapping quality histogram
- discordant.mapq_bins[mapq]++;
- discordant.mapq_log_bins[log_mapq]++;
- // count this read as mapped
- discordant.n_mapped++;
- if (!alignment1.second_best().is_paired())
- {
- // we only have one score; count as a unique alignment
- discordant.n_unique++;
- }
- else
- {
- // we have two best scores, which implies two (or more) alignment positions
- // count as multiple alignment
- discordant.n_multiple++;
- }
- // compute final alignment score
- const int32 first = alignment1.best().score() + alignment2.best().score();
- const int32 second = alignment1.second_best().is_paired() ?
- alignment1.second_best().score() + alignment2.second_best().score() :
- Field_traits<int32>::min();
- // if the two best scores are equal, count as ambiguous
- if (first == second)
- discordant.n_ambiguous++;
- else {
- // else, the first score must be higher...
- NVBIO_CUDA_ASSERT(first > second);
- /// ... which counts as a nonambiguous alignment
- discordant.n_unambiguous++;
- }
- // compute edit distance scores
- const uint32 first_ed = alignment1.best().ed() + alignment2.best().ed();
- const uint32 second_ed = alignment1.second_best().is_paired() ?
- alignment1.second_best().ed() + alignment2.second_best().ed() : 255u;
- // update best edit-distance histograms
- if (first_ed < discordant.mapped_ed_histogram.size())
- {
- discordant.mapped_ed_histogram[first_ed]++;
- if (alignment1.best().is_rc())
- discordant.mapped_ed_histogram_fwd[first_ed]++;
- else
- discordant.mapped_ed_histogram_rev[first_ed]++;
- const uint32 log_first_ed = first_ed ? nvbio::log2(first_ed) + 1 : 0;
- discordant.mapped_log_ed_histogram[log_first_ed]++;
- }
- // track edit-distance correlation
- if (first_ed + 1 < 64)
- {
- if (second_ed + 1 < 64)
- discordant.mapped_ed_correlation[first_ed + 1][second_ed + 1]++;
- else
- discordant.mapped_ed_correlation[first_ed + 1][0]++;
- }
- }
- else
- {
- //
- // track discordand alignments separately for each mate
- //
- const io::BestAlignments& aln1 = alignment1.best().mate() == 0 ? alignment1 : alignment2;
- const io::BestAlignments& aln2 = alignment1.best().mate() == 0 ? alignment2 : alignment1;
- track_alignment_statistics( &mate1, aln1, mapq );
- track_alignment_statistics( &mate2, aln2, mapq );
- }
- }
- void Stats::track_alignment_statistics(
- AlignmentStats* mate,
- const io::BestAlignments& alignment,
- const uint8 mapq)
- {
- // check if the mate is aligned
- if (!alignment.best().is_aligned())
- {
- mate->mapped_ed_correlation[0][0]++;
- return;
- }
- // count this read as mapped
- mate->n_mapped++;
- const uint32 log_mapq = mapq ? nvbio::log2(mapq) + 1u : 0u;
- // keep track of mapping quality histogram
- mate->mapq_bins[mapq]++;
- mate->mapq_log_bins[log_mapq]++;
- if (!alignment.second_best().is_aligned())
- {
- // we only have one score; count as a unique alignment
- mate->n_unique++;
- }
- else
- {
- // we have two best scores, which implies two (or more) alignment positions
- // count as multiple alignment
- mate->n_multiple++;
- }
- // compute final alignment score
- const int32 first = alignment.best().score();
- const int32 second = alignment.second_best().score();
- // if the two best scores are equal, count as ambiguous
- if (first == second)
- mate->n_ambiguous++;
- else {
- // else, the first score must be higher...
- NVBIO_CUDA_ASSERT(first > second);
- /// ... which counts as a nonambiguous alignment
- mate->n_unambiguous++;
- }
- // compute edit distance scores
- const uint32 first_ed = alignment.best().ed();
- const uint32 second_ed = alignment.second_best().ed();
- // update best edit-distance histograms
- if (first_ed < mate->mapped_ed_histogram.size())
- {
- mate->mapped_ed_histogram[first_ed]++;
- if (alignment.best().is_rc())
- mate->mapped_ed_histogram_fwd[first_ed]++;
- else
- mate->mapped_ed_histogram_rev[first_ed]++;
- const uint32 log_first_ed = first_ed ? nvbio::log2(first_ed) + 1 : 0;
- mate->mapped_log_ed_histogram[log_first_ed]++;
- }
- // track edit-distance correlation
- if (first_ed + 1 < 64)
- {
- if (second_ed + 1 < 64)
- mate->mapped_ed_correlation[first_ed + 1][second_ed + 1]++;
- else
- mate->mapped_ed_correlation[first_ed + 1][0]++;
- }
- }
- namespace { // anonymous
- std::string generate_file_name(const char* report, const uint32 id, const char* name)
- {
- std::string file_name = report;
- char id_name[2048]; sprintf( id_name, "%u.%s", id, name );
- {
- const size_t offset = file_name.find(".html");
- file_name.replace( offset+1, file_name.length() - offset - 1, id_name );
- file_name.append( ".html" );
- }
- return file_name;
- }
- std::string device_file_name(const char* report, const uint32 i)
- {
- std::string file_name = report;
- char name[32]; sprintf( name, "%u", i );
- {
- const size_t offset = file_name.find(".html");
- file_name.replace( offset+1, file_name.length() - offset - 1, name );
- file_name.append( ".html" );
- }
- return file_name;
- }
- // return the local file name from a path
- //
- const char* local_file(const std::string& file_name)
- {
- #if WIN32
- const size_t pos = file_name.find_last_of("/\\");
- #else
- const size_t pos = file_name.rfind('/');
- #endif
- if (pos == std::string::npos)
- return file_name.c_str();
- else
- return file_name.c_str() + pos + 1u;
- }
- void add_param(FILE* html_output, const char* name, const uint32 val, bool alt)
- {
- html::tr_object tr( html_output, "class", alt ? "alt" : "none", NULL );
- html::th_object( html_output, html::FORMATTED, NULL, name );
- html::td_object( html_output, html::FORMATTED, NULL, "%u", val );
- }
- void add_param(FILE* html_output, const char* name, const float val, bool alt)
- {
- html::tr_object tr( html_output, "class", alt ? "alt" : "none", NULL );
- html::th_object( html_output, html::FORMATTED, NULL, name );
- html::td_object( html_output, html::FORMATTED, NULL, "%f", val );
- }
- void add_param(FILE* html_output, const char* name, const char* val, bool alt)
- {
- html::tr_object tr( html_output, "class", alt ? "alt" : "none", NULL );
- html::th_object( html_output, html::FORMATTED, NULL, name );
- html::td_object( html_output, html::FORMATTED, NULL, "%s", val );
- }
- void stats_string(char* buffer, const uint32 px, const char* units, const float v, const float p, const float range)
- {
- sprintf(buffer,"<span><statnum style=\"width:%upx;\">%.1f %s</statnum> <statbar style=\"width:%.1f%%%%\">\'</statbar></span>", px, v, units, 2.0f + range * p);
- }
- } // anonymous namespace
- void generate_report_header(const uint32 n_reads, const Params& params, AlignmentStats& aln_stats, const uint32 n_devices, const Stats* device_stats, const char* report)
- {
- if (report == NULL)
- return;
- FILE* html_output = fopen( report, "w" );
- if (html_output == NULL)
- {
- log_warning( stderr, "unable to write HTML report \"%s\"\n", report );
- return;
- }
- {
- const uint32 n_mapped = aln_stats.n_mapped;
- html::html_object html( html_output );
- {
- const char* meta_list = "<meta http-equiv=\"refresh\" content=\"2\" />";
- html::header_object hd( html_output, "Bowtie2 Report", html::style(), meta_list );
- {
- html::body_object body( html_output );
- //
- // params
- //
- {
- html::table_object table( html_output, "params", "params", "parameters" );
- {
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "parameter name" );
- html::th_object( html_output, html::FORMATTED, NULL, "value" );
- }
- add_param( html_output, "randomized", params.randomized ? "yes" : "no", true );
- add_param( html_output, "N", params.allow_sub, false );
- add_param( html_output, "seed-len", params.seed_len, true );
- add_param( html_output, "subseed-len", params.subseed_len, false );
- add_param( html_output, "seed-freq", params.seed_freq.type_symbol(), true );
- add_param( html_output, "seed-freq", params.seed_freq.k, true );
- add_param( html_output, "seed-freq", params.seed_freq.m, true );
- add_param( html_output, "max-reseed", params.max_reseed, false );
- add_param( html_output, "rep-seeds", params.rep_seeds, true );
- add_param( html_output, "max-hits", params.max_hits, false );
- add_param( html_output, "max-dist", params.max_dist, true );
- add_param( html_output, "max-effort", params.max_effort, false );
- add_param( html_output, "min-ext", params.min_ext, true );
- add_param( html_output, "max-ext", params.max_ext, false );
- add_param( html_output, "mapQ-filter", params.mapq_filter, true );
- add_param( html_output, "scoring", params.scoring_file.c_str(), false );
- add_param( html_output, "report", params.report.c_str(), true );
- }
- //
- // per-device stats
- //
- {
- char span_string[1024];
- html::table_object table( html_output, "device-stats", "stats", "device stats" );
- {
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "" );
- html::th_object( html_output, html::FORMATTED, NULL, "time" );
- html::th_object( html_output, html::FORMATTED, NULL, "avg speed" );
- html::th_object( html_output, html::FORMATTED, NULL, "reads" );
- }
- float global_time = 0.0f;
- for (uint32 i = 0; i < n_devices; ++i)
- global_time += device_stats[i].global_time;
- for (uint32 i = 0; i < n_devices; ++i)
- {
- char link_name[1024];
- char device_name[64];
- sprintf( device_name, "device %u", i );
- sprintf( link_name, "<a href=\"%s\">%s</a>", local_file( device_file_name( report, i ) ), device_name );
- const char* cls = "none";
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, link_name );
- stats_string( span_string, 40, "s", device_stats[i].global_time, device_stats[i].global_time / global_time, 75.0f );
- html::td_object( html_output, html::FORMATTED, "class", cls, NULL, span_string );
- html::td_object( html_output, html::FORMATTED, NULL, "%.2f K reads/s", 1.0e-3f * float(device_stats[i].n_reads) / device_stats[i].global_time );
- html::td_object( html_output, html::FORMATTED, NULL, "%.2f M", float(device_stats[i].n_reads) * 1.0e-6f );
- }
- }
- //
- // mapping stats
- //
- {
- html::table_object table( html_output, "mapping-stats", "stats", "mapping stats" );
- {
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "" );
- html::th_object( html_output, html::FORMATTED, NULL, "mapped" );
- html::th_object( html_output, html::FORMATTED, NULL, "ambiguous" );
- html::th_object( html_output, html::FORMATTED, NULL, "multiple" );
- }
- {
- html::tr_object tr( html_output, "class", "alt", NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "reads" );
- html::td_object( html_output, html::FORMATTED, NULL, "%.1f %%", 100.0f * float(n_mapped)/float(n_reads) );
- html::td_object( html_output, html::FORMATTED, NULL, "%.1f %%", 100.0f * float(aln_stats.n_ambiguous)/float(n_reads) );
- html::td_object( html_output, html::FORMATTED, NULL, "%.1f %%", 100.0f * float(aln_stats.n_multiple)/float(n_reads) );
- }
- {
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "edit distance" );
- html::th_object( html_output, html::FORMATTED, NULL, "total" );
- html::th_object( html_output, html::FORMATTED, NULL, "forward" );
- html::th_object( html_output, html::FORMATTED, NULL, "reverse" );
- }
- uint32 best_bin[2] = {0};
- uint32 best_bin_val[2] = {0};
- for (uint32 i = 0; i < aln_stats.mapped_ed_histogram.size(); ++i)
- {
- const uint32 v = aln_stats.mapped_ed_histogram[i];
- if (best_bin_val[0] < v)
- {
- best_bin_val[1] = best_bin_val[0];
- best_bin[1] = best_bin[0];
- best_bin_val[0] = v;
- best_bin[0] = i;
- }
- else if (best_bin_val[1] < v)
- {
- best_bin_val[1] = v;
- best_bin[1] = i;
- }
- }
- for (uint32 i = 0; i < aln_stats.mapped_ed_histogram.size(); ++i)
- {
- const uint32 v = aln_stats.mapped_ed_histogram[i];
- const uint32 vf = aln_stats.mapped_ed_histogram_fwd[i];
- const uint32 vr = aln_stats.mapped_ed_histogram_rev[i];
- if (float(v)/float(n_reads) < 1.0e-3f)
- continue;
- html::tr_object tr( html_output, "class", i % 2 ? "none" : "alt", NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "%u", i );
- const char* cls = i == best_bin[0] ? "yellow" : i == best_bin[1] ? "orange" : "none";
- html::td_object( html_output, html::FORMATTED, "class", cls, NULL, "%.1f %%", 100.0f * float(v)/float(n_reads) );
- html::td_object( html_output, html::FORMATTED, NULL, "%.1f %%", 100.0f * float(vf)/float(n_reads) );
- html::td_object( html_output, html::FORMATTED, NULL, "%.1f %%", 100.0f * float(vr)/float(n_reads) );
- }
- }
- //
- // mapping quality stats
- //
- {
- html::table_object table( html_output, "mapping-quality-stats", "stats", "mapping quality stats" );
- {
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "mapQ" );
- html::th_object( html_output, html::FORMATTED, NULL, "percentage" );
- }
- // rebin to a logarithmic scale
- uint64 bins[7] = {0};
- for (uint32 i = 0; i < 64; ++i)
- {
- const uint32 log_mapq = i ? nvbio::log2(i) + 1 : 0;
- bins[log_mapq] += aln_stats.mapq_bins[i];
- }
- // compute best bins
- uint32 best_bin[2] = {0};
- uint64 best_bin_val[2] = {0};
- for (uint32 i = 0; i < 7; ++i)
- {
- if (best_bin_val[0] < bins[i])
- {
- best_bin_val[1] = best_bin_val[0];
- best_bin[1] = best_bin[0];
- best_bin_val[0] = bins[i];
- best_bin[0] = i;
- }
- else if (best_bin_val[1] < bins[i])
- {
- best_bin_val[1] = bins[i];
- best_bin[1] = i;
- }
- }
- // output html table
- for (uint32 i = 0; i < 7; ++i)
- {
- const uint32 bin_size = 1u << (i-1);
- char buffer[1024];
- if (i <= 1)
- sprintf( buffer, "%u", i );
- else if (bin_size < 1024)
- sprintf( buffer, "%u - %u", bin_size, bin_size*2-1 );
- html::tr_object tr( html_output, "class", i % 2 ? "none" : "alt", NULL );
- html::th_object( html_output, html::FORMATTED, NULL, buffer );
- const char* cls = i == best_bin[0] ? "yellow" : i == best_bin[1] ? "orange" : "none";
- html::td_object( html_output, html::FORMATTED, "class", cls, NULL, "%.1f %%", 100.0f * float(bins[i])/float(n_reads) );
- }
- }
- //
- // best2-mapping stats
- //
- {
- // compute best 2 entries among double alignments
- uint2 best_bin2[2] = { make_uint2(0,0) };
- uint32 best_bin2_val[2] = { 0 };
- for (uint32 i = 1; i <= 16; ++i)
- {
- for (uint32 j = 1; j <= 16; ++j)
- {
- if (best_bin2_val[0] < aln_stats.mapped_ed_correlation[i][j])
- {
- best_bin2_val[1] = best_bin2_val[0];
- best_bin2[1] = best_bin2[0];
- best_bin2_val[0] = aln_stats.mapped_ed_correlation[i][j];
- best_bin2[0] = make_uint2(i,j);
- }
- else if (best_bin2_val[1] < aln_stats.mapped_ed_correlation[i][j])
- {
- best_bin2_val[1] = aln_stats.mapped_ed_correlation[i][j];
- best_bin2[1] = make_uint2(i,j);
- }
- }
- }
- // compute best 2 entries among single alignments
- uint2 best_bin1[2] = { make_uint2(0,0) };
- uint32 best_bin1_val[2] = { 0 };
- for (uint32 i = 0; i <= 16; ++i)
- {
- if (best_bin1_val[0] < aln_stats.mapped_ed_correlation[i][0])
- {
- best_bin1_val[1] = best_bin1_val[0];
- best_bin1[1] = best_bin1[0];
- best_bin1_val[0] = aln_stats.mapped_ed_correlation[i][0];
- best_bin1[0] = make_uint2(i,0);
- }
- else if (best_bin1_val[1] < aln_stats.mapped_ed_correlation[i][0])
- {
- best_bin1_val[1] = aln_stats.mapped_ed_correlation[i][0];
- best_bin1[1] = make_uint2(i,0);
- }
- }
- html::table_object table( html_output, "best2-mapping-stats", "stats", "best2 mapping stats" );
- {
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "" );
- for (uint32 i = 0; i <= 16; ++i)
- html::th_object( html_output, html::FORMATTED, NULL, (i == 0 ? "-" : "%u"), i-1 );
- }
- for (uint32 i = 0; i <= 16; ++i)
- {
- html::tr_object tr( html_output, "class", i % 2 ? "none" : "alt", NULL );
- html::th_object( html_output, html::FORMATTED, NULL, (i == 0 ? "-" : "%u"), i-1 );
- for (uint32 j = 0; j <= 16; ++j)
- {
- const uint32 v = aln_stats.mapped_ed_correlation[i][j];
- if (100.0f * float(v)/float(n_reads) >= 0.1f)
- {
- const char* cls = ((i == best_bin1[0].x && j == best_bin1[0].y) ||
- (i == best_bin2[0].x && j == best_bin2[0].y)) ? "yellow" :
- ((i == best_bin1[1].x && j == best_bin1[1].y) ||
- (i == best_bin2[1].x && j == best_bin2[1].y)) ? "orange" :
- (i == j) ? "pink" :
- (i+1 == j) ? "azure" : "none";
- html::td_object( html_output, html::FORMATTED, "class", cls, NULL, "%.1f %%", 100.0f * float(v)/float(n_reads) );
- }
- else if (100.0f * float(v)/float(n_reads) >= 0.01f)
- html::td_object( html_output, html::FORMATTED, "class", "small", NULL, "%.2f %%", 100.0f * float(v)/float(n_reads) );
- else
- {
- const char* cls = (i > params.max_dist+1 || j > params.max_dist+1) ? "gray" : "none";
- html::td_object( html_output, html::FORMATTED, "class", cls, NULL, "-" );
- }
- }
- }
- }
- }
- }
- }
- fclose( html_output );
- }
- void generate_device_report(const uint32 id, Stats& stats, AlignmentStats& aln_stats, const char* report)
- {
- if (report == NULL)
- return;
- std::vector<KernelStats*> kernel_stats;
- kernel_stats.push_back( &stats.map );
- kernel_stats.push_back( &stats.select );
- kernel_stats.push_back( &stats.sort );
- kernel_stats.push_back( &stats.locate );
- kernel_stats.push_back( &stats.score );
- kernel_stats.push_back( &stats.opposite_score );
- kernel_stats.push_back( &stats.backtrack );
- kernel_stats.push_back( &stats.backtrack_opposite );
- kernel_stats.push_back( &stats.finalize );
- kernel_stats.push_back( &stats.alignments_DtoH );
- kernel_stats.push_back( &stats.read_HtoD );
- kernel_stats.push_back( &stats.read_io );
- //if (stats.params.keep_stats)
- {
- for (uint32 i = 0; i < kernel_stats.size(); ++i)
- generate_kernel_table( id, report, *kernel_stats[i] );
- }
- const std::string device_report = device_file_name( report, id );
- FILE* html_output = fopen( device_report.c_str(), "w" );
- if (html_output == NULL)
- {
- log_warning( stderr, "unable to write HTML report \"%s\"\n", device_report.c_str() );
- return;
- }
- {
- const uint32 n_reads = stats.n_reads;
- const uint32 n_mapped = aln_stats.n_mapped;
- html::html_object html( html_output );
- {
- const char* meta_list = "<meta http-equiv=\"refresh\" content=\"2\" />";
- html::header_object hd( html_output, "Bowtie2 Report", html::style(), meta_list );
- {
- html::body_object body( html_output );
- //
- // speed stats
- //
- {
- char span_string[1024];
- html::table_object table( html_output, "speed-stats", "stats", "speed stats" );
- float worst_time[2] = {0};
- uint32 worst[2] = {0};
- for (uint32 i = 0; i < kernel_stats.size(); ++i)
- {
- const float time = kernel_stats[i]->time;
- if (worst_time[0] < time)
- {
- worst_time[1] = worst_time[0];
- worst[1] = worst[0];
- worst_time[0] = time;
- worst[0] = i;
- }
- else if (worst_time[1] < time)
- {
- worst_time[1] = time;
- worst[1] = i;
- }
- }
- {
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "" );
- html::th_object( html_output, html::FORMATTED, NULL, "time" );
- html::th_object( html_output, html::FORMATTED, NULL, "avg speed" );
- html::th_object( html_output, html::FORMATTED, NULL, "max speed" );
- }
- {
- html::tr_object tr( html_output, "class", "alt", NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "total" );
- html::td_object( html_output, html::FORMATTED, "class", "red", NULL, "%.1f s", stats.global_time );
- html::td_object( html_output, html::FORMATTED, NULL, "%.1f K reads/s", 1.0e-3f * float(n_reads)/stats.global_time );
- html::td_object( html_output, "-", NULL );
- }
- for (uint32 i = 0; i < kernel_stats.size(); ++i)
- {
- const KernelStats& kstats = *kernel_stats[i];
- const char* name = kstats.name.c_str();
- const char* units = kstats.units.c_str();
- const std::string file_name = generate_file_name( report, id, name );
- char link_name[1024];
- sprintf( link_name, "<a href=\"%s\">%s</a>", local_file( file_name ), name );
- const char* cls = worst[0] == i ? "yellow" : worst[1] == i ? "orange" : "none";
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, link_name );
- stats_string( span_string, 40, "s", kstats.time, kstats.time / stats.global_time, 75.0f );
- html::td_object( html_output, html::FORMATTED, "class", cls, NULL, span_string );
- html::td_object( html_output, html::FORMATTED, NULL, "%.2f M %s/s", 1.0e-6f * float(kstats.calls)/kstats.time, units );
- html::td_object( html_output, html::FORMATTED, NULL, "%.2f M %s/s", 1.0e-6f * kstats.max_speed, units );
- }
- }
- //
- // mapping stats
- //
- {
- html::table_object table( html_output, "mapping-stats", "stats", "mapping stats" );
- {
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "" );
- html::th_object( html_output, html::FORMATTED, NULL, "mapped" );
- html::th_object( html_output, html::FORMATTED, NULL, "ambiguous" );
- html::th_object( html_output, html::FORMATTED, NULL, "multiple" );
- }
- {
- html::tr_object tr( html_output, "class", "alt", NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "reads" );
- html::td_object( html_output, html::FORMATTED, NULL, "%.1f %%", 100.0f * float(n_mapped)/float(n_reads) );
- html::td_object( html_output, html::FORMATTED, NULL, "%.1f %%", 100.0f * float(aln_stats.n_ambiguous)/float(n_reads) );
- html::td_object( html_output, html::FORMATTED, NULL, "%.1f %%", 100.0f * float(aln_stats.n_multiple)/float(n_reads) );
- }
- {
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "edit distance" );
- html::th_object( html_output, html::FORMATTED, NULL, "total" );
- html::th_object( html_output, html::FORMATTED, NULL, "forward" );
- html::th_object( html_output, html::FORMATTED, NULL, "reverse" );
- }
- uint32 best_bin[2] = {0};
- uint32 best_bin_val[2] = {0};
- for (uint32 i = 0; i < aln_stats.mapped_ed_histogram.size(); ++i)
- {
- const uint32 v = aln_stats.mapped_ed_histogram[i];
- if (best_bin_val[0] < v)
- {
- best_bin_val[1] = best_bin_val[0];
- best_bin[1] = best_bin[0];
- best_bin_val[0] = v;
- best_bin[0] = i;
- }
- else if (best_bin_val[1] < v)
- {
- best_bin_val[1] = v;
- best_bin[1] = i;
- }
- }
- for (uint32 i = 0; i < aln_stats.mapped_ed_histogram.size(); ++i)
- {
- const uint32 v = aln_stats.mapped_ed_histogram[i];
- const uint32 vf = aln_stats.mapped_ed_histogram_fwd[i];
- const uint32 vr = aln_stats.mapped_ed_histogram_rev[i];
- if (float(v)/float(n_reads) < 1.0e-3f)
- continue;
- html::tr_object tr( html_output, "class", i % 2 ? "none" : "alt", NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "%u", i );
- const char* cls = i == best_bin[0] ? "yellow" : i == best_bin[1] ? "orange" : "none";
- html::td_object( html_output, html::FORMATTED, "class", cls, NULL, "%.1f %%", 100.0f * float(v)/float(n_reads) );
- html::td_object( html_output, html::FORMATTED, NULL, "%.1f %%", 100.0f * float(vf)/float(n_reads) );
- html::td_object( html_output, html::FORMATTED, NULL, "%.1f %%", 100.0f * float(vr)/float(n_reads) );
- }
- }
- //
- // mapping quality stats
- //
- {
- html::table_object table( html_output, "mapping-quality-stats", "stats", "mapping quality stats" );
- {
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "mapQ" );
- html::th_object( html_output, html::FORMATTED, NULL, "percentage" );
- }
- // rebin to a logarithmic scale
- uint64 bins[7] = {0};
- for (uint32 i = 0; i < 64; ++i)
- {
- const uint32 log_mapq = i ? nvbio::log2(i) + 1 : 0;
- bins[log_mapq] += aln_stats.mapq_bins[i];
- }
- // compute best bins
- uint32 best_bin[2] = {0};
- uint64 best_bin_val[2] = {0};
- for (uint32 i = 0; i < 7; ++i)
- {
- if (best_bin_val[0] < bins[i])
- {
- best_bin_val[1] = best_bin_val[0];
- best_bin[1] = best_bin[0];
- best_bin_val[0] = bins[i];
- best_bin[0] = i;
- }
- else if (best_bin_val[1] < bins[i])
- {
- best_bin_val[1] = bins[i];
- best_bin[1] = i;
- }
- }
- // output html table
- for (uint32 i = 0; i < 7; ++i)
- {
- const uint32 bin_size = 1u << (i-1);
- char buffer[1024];
- if (i <= 1)
- sprintf( buffer, "%u", i );
- else if (bin_size < 1024)
- sprintf( buffer, "%u - %u", bin_size, bin_size*2-1 );
- html::tr_object tr( html_output, "class", i % 2 ? "none" : "alt", NULL );
- html::th_object( html_output, html::FORMATTED, NULL, buffer );
- const char* cls = i == best_bin[0] ? "yellow" : i == best_bin[1] ? "orange" : "none";
- html::td_object( html_output, html::FORMATTED, "class", cls, NULL, "%.1f %%", 100.0f * float(bins[i])/float(n_reads) );
- }
- }
- //
- // best2-mapping stats
- //
- {
- // compute best 2 entries among double alignments
- uint2 best_bin2[2] = { make_uint2(0,0) };
- uint32 best_bin2_val[2] = { 0 };
- for (uint32 i = 1; i <= 16; ++i)
- {
- for (uint32 j = 1; j <= 16; ++j)
- {
- if (best_bin2_val[0] < aln_stats.mapped_ed_correlation[i][j])
- {
- best_bin2_val[1] = best_bin2_val[0];
- best_bin2[1] = best_bin2[0];
- best_bin2_val[0] = aln_stats.mapped_ed_correlation[i][j];
- best_bin2[0] = make_uint2(i,j);
- }
- else if (best_bin2_val[1] < aln_stats.mapped_ed_correlation[i][j])
- {
- best_bin2_val[1] = aln_stats.mapped_ed_correlation[i][j];
- best_bin2[1] = make_uint2(i,j);
- }
- }
- }
- // compute best 2 entries among single alignments
- uint2 best_bin1[2] = { make_uint2(0,0) };
- uint32 best_bin1_val[2] = { 0 };
- for (uint32 i = 0; i <= 16; ++i)
- {
- if (best_bin1_val[0] < aln_stats.mapped_ed_correlation[i][0])
- {
- best_bin1_val[1] = best_bin1_val[0];
- best_bin1[1] = best_bin1[0];
- best_bin1_val[0] = aln_stats.mapped_ed_correlation[i][0];
- best_bin1[0] = make_uint2(i,0);
- }
- else if (best_bin1_val[1] < aln_stats.mapped_ed_correlation[i][0])
- {
- best_bin1_val[1] = aln_stats.mapped_ed_correlation[i][0];
- best_bin1[1] = make_uint2(i,0);
- }
- }
- html::table_object table( html_output, "best2-mapping-stats", "stats", "best2 mapping stats" );
- {
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "" );
- for (uint32 i = 0; i <= 16; ++i)
- html::th_object( html_output, html::FORMATTED, NULL, (i == 0 ? "-" : "%u"), i-1 );
- }
- for (uint32 i = 0; i <= 16; ++i)
- {
- html::tr_object tr( html_output, "class", i % 2 ? "none" : "alt", NULL );
- html::th_object( html_output, html::FORMATTED, NULL, (i == 0 ? "-" : "%u"), i-1 );
- for (uint32 j = 0; j <= 16; ++j)
- {
- const uint32 v = aln_stats.mapped_ed_correlation[i][j];
- if (100.0f * float(v)/float(n_reads) >= 0.1f)
- {
- const char* cls = ((i == best_bin1[0].x && j == best_bin1[0].y) ||
- (i == best_bin2[0].x && j == best_bin2[0].y)) ? "yellow" :
- ((i == best_bin1[1].x && j == best_bin1[1].y) ||
- (i == best_bin2[1].x && j == best_bin2[1].y)) ? "orange" :
- (i == j) ? "pink" :
- (i+1 == j) ? "azure" : "none";
- html::td_object( html_output, html::FORMATTED, "class", cls, NULL, "%.1f %%", 100.0f * float(v)/float(n_reads) );
- }
- else if (100.0f * float(v)/float(n_reads) >= 0.01f)
- html::td_object( html_output, html::FORMATTED, "class", "small", NULL, "%.2f %%", 100.0f * float(v)/float(n_reads) );
- else
- {
- const char* cls = (i > stats.params.max_dist+1 || j > stats.params.max_dist+1) ? "gray" : "none";
- html::td_object( html_output, html::FORMATTED, "class", cls, NULL, "-" );
- }
- }
- }
- }
- //
- // seeding stats
- //
- if (stats.params.keep_stats)
- {
- // copy stats locally
- uint64 hits_total = stats.hits_total;
- uint64 hits_ranges = stats.hits_ranges;
- uint32 hits_max = stats.hits_max;
- uint32 hits_max_range = stats.hits_max_range;
- uint64 hits_top_total = stats.hits_top_total;
- uint32 hits_top_max = stats.hits_top_max;
- uint64 hits_bins[28];
- uint64 hits_bins_sum = 0;
- uint64 hits_top_bins[28];
- uint64 hits_top_bins_sum = 0;
- for (uint32 i = 0; i < 28; ++i)
- {
- hits_bins_sum += hits_bins[i] = stats.hits_bins[i];
- hits_top_bins_sum += hits_top_bins[i] = stats.hits_top_bins[i];
- }
- html::table_object table( html_output, "seeding-stats", "stats", "seeding stats" );
- char buffer[1024];
- {
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "" );
- html::th_object( html_output, html::FORMATTED, NULL, "seed hits" );
- html::th_object( html_output, html::FORMATTED, NULL, "top-seed hits" );
- html::th_object( html_output, html::FORMATTED, NULL, "seed ranges" );
- html::th_object( html_output, html::FORMATTED, NULL, "range size" );
- }
- {
- html::tr_object tr( html_output, "class", "alt", NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "avg" );
- html::td_object( html_output, html::FORMATTED, NULL, "%.1f", float(hits_total)/float(n_reads) );
- html::td_object( html_output, html::FORMATTED, NULL, "%.1f", float(hits_top_total)/float(n_reads) );
- html::td_object( html_output, html::FORMATTED, NULL, "%.1f", float(hits_ranges)/float(n_reads) );
- html::td_object( html_output, html::FORMATTED, NULL, "%.1f", float(hits_total)/float(hits_ranges) );
- }
- {
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "max" );
- html::td_object( html_output, html::FORMATTED, NULL, "%u", hits_max );
- html::td_object( html_output, html::FORMATTED, NULL, "%u", hits_top_max );
- html::td_object( html_output, html::FORMATTED, NULL, "" );
- html::td_object( html_output, html::FORMATTED, NULL, "%u", hits_max_range );
- }
- {
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "# hits" );
- html::th_object( html_output, html::FORMATTED, NULL, "%% of seeds" );
- html::th_object( html_output, html::FORMATTED, NULL, "%% of top-seeds" );
- html::th_object( html_output, html::FORMATTED, NULL, "" );
- html::th_object( html_output, html::FORMATTED, NULL, "" );
- }
- uint32 max_bin = 0;
- uint32 best_bin[2] = {0};
- uint64 best_bin_val[2] = {0};
- uint32 best_top_bin[2] = {0};
- uint64 best_top_bin_val[2] = {0};
- for (uint32 i = 0; i < 28; ++i)
- {
- max_bin = float(hits_bins[i]) / float(hits_bins_sum) > 0.001f ? i : max_bin;
- max_bin = float(hits_top_bins[i]) / float(hits_top_bins_sum) > 0.001f ? i : max_bin;
- if (best_bin_val[0] < hits_bins[i])
- {
- best_bin_val[1] = best_bin_val[0];
- best_bin[1] = best_bin[0];
- best_bin_val[0] = hits_bins[i];
- best_bin[0] = i;
- }
- else if (best_bin_val[1] < hits_bins[i])
- {
- best_bin_val[1] = hits_bins[i];
- best_bin[1] = i;
- }
- if (best_top_bin_val[0] < hits_top_bins[i])
- {
- best_top_bin_val[1] = best_top_bin_val[0];
- best_top_bin[1] = best_top_bin[0];
- best_top_bin_val[0] = hits_top_bins[i];
- best_top_bin[0] = i;
- }
- else if (best_top_bin_val[1] < hits_top_bins[i])
- {
- best_top_bin_val[1] = hits_top_bins[i];
- best_top_bin[1] = i;
- }
- }
- for (uint32 i = 0; i < max_bin; ++i)
- {
- const uint32 bin_size = 1u << (i-1);
- html::tr_object tr( html_output, "class", i % 2 ? "none" : "alt", NULL );
- if (i <= 1)
- sprintf( buffer, "%u", i );
- else if (bin_size < 512)
- sprintf( buffer, "%u - %u", bin_size, bin_size*2-1 );
- else if (bin_size == 512)
- sprintf( buffer, "0.5K - 1K" );
- else
- sprintf( buffer, "%uK - %uK", bin_size/1024, bin_size*2/1024 );
- const char* cls = i == best_bin[0] ? "yellow" : i == best_bin[1] ? "orange" : "none";
- const char* cls_top = i == best_top_bin[0] ? "yellow" : i == best_top_bin[1] ? "orange" : "none";
- html::th_object( html_output, html::FORMATTED, NULL, buffer );
- html::td_object( html_output, html::FORMATTED, "class", cls, NULL, "%4.1f %%", 100.0f * float(hits_bins[i]) / float(hits_bins_sum) );
- html::td_object( html_output, html::FORMATTED, "class", cls_top, NULL, "%4.1f %%", 100.0f * float(hits_top_bins[i]) / float(hits_top_bins_sum) );
- html::td_object( html_output, html::FORMATTED, NULL, "" );
- html::td_object( html_output, html::FORMATTED, NULL, "" );
- }
- }
- }
- }
- }
- fclose( html_output );
- }
- template <typename T>
- void find_gt2(const uint32 n, const T* table, uint32 best_bin[2])
- {
- best_bin[0] = best_bin[1] = 0;
- T best_bin_val[2] = {0};
- for (uint32 i = 0; i < n; ++i)
- {
- if (best_bin_val[0] < table[i])
- {
- best_bin_val[1] = best_bin_val[0];
- best_bin[1] = best_bin[0];
- best_bin_val[0] = table[i];
- best_bin[0] = i;
- }
- else if (best_bin_val[1] < table[i])
- {
- best_bin_val[1] = table[i];
- best_bin[1] = i;
- }
- }
- }
- void generate_kernel_table(const uint32 id, const char* report, const KernelStats& stats)
- {
- const char* name = stats.name.c_str();
- const char* units = stats.units.c_str();
- const std::string file_name = generate_file_name( report, id, name );
- const std::deque< std::pair<uint32,float> >& table = stats.info;
- FILE* html_output = fopen( file_name.c_str(), "w" );
- if (html_output == NULL)
- {
- log_warning( stderr, "unable to write HTML report \"%s\"\n", file_name.c_str() );
- return;
- }
- {
- html::html_object html( html_output );
- {
- const char* meta_list = "<meta http-equiv=\"refresh\" content=\"2\" />";
- html::header_object hd( html_output, "Bowtie2 Report", html::style(), meta_list );
- {
- html::body_object body( html_output );
- //
- // kernel summary stats
- //
- {
- uint32 bin_calls[32] = {0};
- float bin_sum_time[32] = {0.0f};
- float bin_avg_time[32] = {0.0f};
- float bin_speed[32] = {0.0f};
- float total_time = stats.time;
- float avg_speed = total_time ? float(double(stats.calls) / double(stats.time)) : 0.0f;
- float max_speed = 0.0f;
- for (uint32 bin = 0; bin < 32; ++bin)
- {
- bin_calls[bin] = stats.bin_calls[bin];
- bin_sum_time[bin] = stats.bin_time[bin];
- bin_avg_time[bin] = stats.bin_calls[bin] ? stats.bin_time[bin] / stats.bin_calls[bin] : 0.0f;
- bin_speed[bin] = stats.bin_time[bin] ? float(double(stats.bin_items[bin]) / double(stats.bin_time[bin])) : 0.0f;
- //bin_speed[bin] = stats.bin_calls[bin] ? stats.bin_speed[bin] / stats.bin_calls[bin] : 0.0f;
- max_speed = std::max( max_speed, bin_speed[bin] );
- }
- char buffer1[1024];
- char buffer2[1024];
- sprintf( buffer1, "%s-summary-stats", name );
- sprintf( buffer2, "%s summary stats", name );
- html::table_object tab( html_output, buffer1, "stats", buffer2 );
- {
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "items" );
- html::td_object( html_output, html::FORMATTED, NULL, "%.2f M", float(stats.calls) * 1.0e-6f );
- }
- // write "user" stats
- for (uint32 i = 0; i < 32; ++i)
- {
- if (stats.user_names[i] == NULL)
- break;
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, stats.user_names[i] );
- html::td_object( html_output, html::FORMATTED, NULL, "%.3f %s",
- stats.user_avg[i] ? stats.user[i]/float(stats.num) :
- stats.user[i],
- stats.user_units[i] );
- }
- {
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "batch size (%s)", units );
- html::th_object( html_output, html::FORMATTED, NULL, "calls" );
- html::th_object( html_output, html::FORMATTED, NULL, "avg time" );
- html::th_object( html_output, html::FORMATTED, NULL, "sum time" );
- html::th_object( html_output, html::FORMATTED, NULL, "cumul. time" );
- html::th_object( html_output, html::FORMATTED, NULL, "speed" );
- }
- uint32 best_avg_bin[2];
- uint32 best_sum_bin[2];
- find_gt2( 32, bin_avg_time, best_avg_bin );
- find_gt2( 32, bin_sum_time, best_sum_bin );
- float cum_time = 0.0f;
- float max_avg_time = 0.0f;
- float max_sum_time = 0.0f;
- for (uint32 i = 0; i < 32; ++i)
- {
- max_avg_time = nvbio::max( bin_avg_time[i], max_avg_time );
- max_sum_time = nvbio::max( bin_sum_time[i], max_sum_time );
- }
- char span_string[1024];
- for (uint32 i = 0; i < 32; ++i)
- {
- if (bin_calls[i] == 0)
- continue;
- const float speed = bin_speed[i];
- cum_time += bin_sum_time[i];
- const uint32 bin_size = 1u << i;
- html::tr_object tr( html_output, "class", i % 2 ? "none" : "alt", NULL );
- if (bin_size == 1)
- html::th_object( html_output, html::FORMATTED, NULL, "1" );
- else if (bin_size < 512)
- html::th_object( html_output, html::FORMATTED, NULL, "%u - %u", bin_size, bin_size*2-1 );
- else if (bin_size == 512)
- html::th_object( html_output, html::FORMATTED, NULL, "512 - 1K" );
- else if (bin_size < 512*1024)
- html::th_object( html_output, html::FORMATTED, NULL, "%uK- %uK", bin_size/1024, (bin_size*2)/1024 );
- else if (bin_size == 512*1024)
- html::th_object( html_output, html::FORMATTED, NULL, "512K - 1M" );
- const char* avg_cls = i == best_avg_bin[0] ? "yellow" : i == best_avg_bin[1] ? "orange" : "none";
- const char* sum_cls = i == best_sum_bin[0] ? "yellow" : i == best_sum_bin[1] ? "orange" : "none";
- const char* spd_cls = speed == max_speed ? "yellow" : speed < avg_speed * 0.1f ? "red" : speed < max_speed * 0.1f ? "pink" : "none";
- html::td_object( html_output, html::FORMATTED, NULL, "%u", bin_calls[i] );
- stats_string( span_string, 60, "ms", 1000.0f * bin_avg_time[i], bin_avg_time[i] / max_avg_time, 50.0f );
- html::td_object( html_output, html::FORMATTED, "class", avg_cls, NULL, span_string );
- stats_string( span_string, 60, "ms", 1000.0f * bin_sum_time[i], bin_sum_time[i] / max_sum_time, 50.0f );
- html::td_object( html_output, html::FORMATTED, "class", sum_cls, NULL, span_string );
- html::td_object( html_output, html::FORMATTED, NULL, "%.1f %%", 100.0f * cum_time / total_time );
- html::td_object( html_output, html::FORMATTED, "class", spd_cls, NULL, "%.1f %c %s/s", speed * (speed >= 1.0e6f ? 1.0e-6f : 1.0e-3f), speed >= 1.0e6f ? 'M' : 'K', units );
- }
- }
- //
- // kernel table stats
- //
- {
- char buffer1[1024];
- char buffer2[1024];
- sprintf( buffer1, "%s-stats", name );
- sprintf( buffer2, "%s stats", name );
- html::table_object tab( html_output, buffer1, "stats", buffer2 );
- {
- html::tr_object tr( html_output, NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "launch" );
- html::th_object( html_output, html::FORMATTED, NULL, "batch size (%s)", units );
- html::th_object( html_output, html::FORMATTED, NULL, "time" );
- html::th_object( html_output, html::FORMATTED, NULL, "speed" );
- }
- uint32 best_bin[2] = {0};
- float best_bin_val[2] = {0};
- for (uint32 i = 0; i < table.size(); ++i)
- {
- if (best_bin_val[0] < table[i].second)
- {
- best_bin_val[1] = best_bin_val[0];
- best_bin[1] = best_bin[0];
- best_bin_val[0] = table[i].second;
- best_bin[0] = i;
- }
- else if (best_bin_val[1] < table[i].second)
- {
- best_bin_val[1] = table[i].second;
- best_bin[1] = i;
- }
- }
- float max_time = 0.0f;
- float max_speed = 0.0f;
- for (uint32 i = 0; i < table.size(); ++i)
- {
- const float speed = float(table[i].first) / table[i].second;
- max_time = nvbio::max( float(table[i].second), max_time );
- max_speed = nvbio::max( speed, max_speed );
- }
- char span_string[1024];
- char units_string[1024];
- for (uint32 i = 0; i < table.size(); ++i)
- {
- const float speed = float(table[i].first) / table[i].second;
- html::tr_object tr( html_output, "class", i % 2 ? "none" : "alt", NULL );
- html::th_object( html_output, html::FORMATTED, NULL, "%u", i );
- const char* cls = i == best_bin[0] ? "yellow" : i == best_bin[1] ? "orange" : "none";
- html::td_object( html_output, html::FORMATTED, NULL, "%.1f %c", float(table[i].first) * (table[i].first > 1000000 ? 1.0e-6f : 1.0e-3f), table[i].first > 1000000 ? 'M' : 'K' );
- stats_string( span_string, 50, "ms", 1000.0f * float(table[i].second), float(table[i].second) / max_time, 50.0f );
- html::td_object( html_output, html::FORMATTED, "class", cls, NULL, span_string );
- sprintf(units_string, "%c %s/s", speed > 1000000 ? 'M' : 'K', units );
- stats_string( span_string, 100, units_string, speed * (speed >= 1.0e6f ? 1.0e-6f : 1.0e-3f), speed / max_speed, 50.0f );
- html::td_object( html_output, html::FORMATTED, NULL, span_string );
- }
- }
- }
- }
- }
- fclose( html_output );
- }
- } // namespace cuda
- } // namespace bowtie2
- } // namespace nvbio
|