void playWithHomeTheater() { // Create all the parts of the home theatre system Amplifier amp("Top-O-Line Amplifier"); CdPlayer cd("Top-O-Line CD Player", &); DvdPlayer dvd("Top-O-Line DVD Player", &); Screen screen("My Theater Screen"); PopcornPopper popper("My Popcorn Popper"); Tuner tuner("Top-O-Line AM/FM Tuner", &); TheaterLights lights("Theater Ceiling Lights"); Projector projector("Top-O-Line Projector"); popper.on(); // Turn on the popcorn popper... popper.pop(); // and start popping... lights.dim(10); // Dim the lights to 10%... screen.down(); // Put the screen down... projector.on(); // Turn on the projector... projector.setInput(&dvd); // set it to DVD... projector.wideScreenMode(); // and put it on wide screen mode for the movie... amp.on(); // Turn on the amp... amp.setInput(&dvd); // set it to DVD and... amp.setSurroundSound(); // put it into surround sound mode... amp.setVolume(11); // and set the volume to 11... dvd.on(); // Turn on the DVD player... dvd.play("Raiders of the lost ark"); // and FINALLY, play the movie! // What about shutting everything down again?! // How would you play a CD? etc... }
EKFState getTunedKalmanState_Gradient( EKFState begin, EKFState step, std::vector<dmod::array1d> signals, int iterationsNumber ) { FilterTuning::GradientTuner tuner(signals, iterationsNumber, begin, step); EKFState tunedParameters = tuner.tune(); return tunedParameters; }
void playWithHomeTheaterFacade() { // Create all the parts of the home theatre system // Not encapsulated or owned by the facade. Amplifier amp("Top-O-Line Amplifier"); CdPlayer cd("Top-O-Line CD Player", &); DvdPlayer dvd("Top-O-Line DVD Player", &); Screen screen("My Theater Screen"); PopcornPopper popper("My Popcorn Popper"); Tuner tuner("Top-O-Line AM/FM Tuner", &); TheaterLights lights("Theater Ceiling Lights"); Projector projector("Top-O-Line Projector"); HomeTheaterFacade theater(&, &tuner, &dvd, &cd, &projector, &lights, &screen, &popper); theater.watchMovie("Raiders of the Lost Ark"); theater.endMovie(); }
///////////////////// ///Tuning/////////// ///////////////////// EKFState getTunedKalmanState_TotalSearch( std::vector<dmod::array1d> signals, size_t filtersAmount, std::default_random_engine &gen ) { //Creation of EKF tuned by TotalSearch EKFState minimal; EKFState maximal; minimal.state = Eigen::Vector4d(0, 0, 0.00, 0); minimal.Rw << 0.01, 0, 0, 0, 0, 0.01, 0, 0, 0, 0, 0.001, 0, 0, 0, 0, 0.002; minimal.R = minimal.Rw; minimal.Rn = 0.1; maximal.state = Eigen::Vector4d(255, 10, 0.6, 2 * M_PI); maximal.Rw << 0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 0.1, 0, 0, 0, 0, 0.2; maximal.R = maximal.Rw; maximal.Rn = 10; //minimal.state = Eigen::Vector4d(0, 0, 0.00, 0); //minimal.Rw << // 0.2, 0, 0, 0, // 0, 0.05, 0, 0, // 0, 0, 0.001, 0, // 0, 0, 0, 0.002; //minimal.R = minimal.Rw; //minimal.Rn = 0.1; //maximal.state = Eigen::Vector4d(255, 5, 0.3, 2 * M_PI); //maximal.Rw = minimal.Rw; //maximal.R = maximal.Rw; //maximal.Rn = 10; FilterTuning::TotalSearchTuner tuner(signals, filtersAmount, gen, minimal, maximal); tuner.createStates(); EKFState tunedParameters = tuner.tune(); return tunedParameters; }
size_t FirFilterDesigner::wdfirCx ( T& filtCoeff, FIRFilter::filter_type type, Real ripple, Real twNorm, Real flNorm, Real fhNorm, size_t minTaps, size_t maxTaps) { if ((type==FIRFilter::lowpass)||(type==FIRFilter::highpass)) { //design a real filter and mux the imaginary zeros in there to make it complex RealArray r; size_t ret = wdfir(r, type, ripple, twNorm, flNorm, 0, minTaps,maxTaps); muxImaginaryZeros(r, filtCoeff); return ret; } else { //create a lowpass or highpass filter and tune the filter with a complex tune to make the bandpass filter FIRFilter::filter_type inputType=FIRFilter::lowpass; if (type==FIRFilter::bandstop) inputType=FIRFilter::highpass; RealArray r; size_t ret = wdfir(r, inputType, ripple, twNorm, fabs(fhNorm-flNorm)/2.0, 0, minTaps,maxTaps); filtCoeff.resize(ret); //tune the filter outputs to the specified center frequency //the tune phase is 2*pi*fc_norm = 2*pi*((fhNorm+flNorm)/2) = pi*(fhNorm+flNorm) Real tunePhaseUpdate=M_PI*(fhNorm+flNorm); Complex phasor(cos(tunePhaseUpdate),sin(tunePhaseUpdate)); Complex tuner(phasor); for (size_t i=0; i!=ret; i++) { filtCoeff[i]=r[i]*tuner; tuner*=phasor; } return ret; } }
/** main */ int main(int argc, char *argv[]) { Args args = parseOption(argc, argv); // 正常終了時戻り値 int result = 0; boost::scoped_ptr<Recordable> tuner(NULL); timeval tv_start; #ifdef UDP Udp udp; #endif /* defined(UDP) */ #ifdef HTTP int dest = 1; // stdout int connected_socket = 0; int listening_socket = 0; #endif /* defined(HTTP) */ // 引数確認 if (!args.forever && args.recsec <= 0) { std::cerr << "recsec must be (recsec > 0)." << std::endl; exit(1); } // 録画時間の基準開始時間 time_t time_start = time(NULL); // ログ出力先設定 std::ostream& log = args.stdout ? std::cerr : std::cout; #ifdef HTTP if( !args.http_mode ){ // 出力先ファイルオープン if(!args.stdout) { dest = open(args.destfile, (O_RDWR | O_CREAT | O_TRUNC), 0666); if (0 > dest) { std::cerr << "can't open file '" << args.destfile << "' to write." << std::endl; exit(1); } } }else{ struct sockaddr_in sin; int sock_optval = 1; int ret; fprintf(stderr, "run as a daemon..\n"); if(daemon(1,1)){ perror("failed to start"); exit(1); } listening_socket = socket(AF_INET, SOCK_STREAM, 0); if ( listening_socket == -1 ){ perror("socket"); exit(1); } if ( setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, &sock_optval, sizeof(sock_optval)) == -1 ){ perror("setsockopt"); exit(1); } sin.sin_family = AF_INET; sin.sin_port = htons(args.http_port); sin.sin_addr.s_addr = htonl(INADDR_ANY); if ( bind(listening_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0 ){ perror("bind"); exit(1); } ret = listen(listening_socket, SOMAXCONN); if ( ret == -1 ){ perror("listen"); exit(1); } fprintf(stderr,"listening at port %d\n", args.http_port); } while(1){ if ( args.http_mode ) { struct sockaddr_in peer_sin; int read_size; unsigned int len; char buffer[256]; char s0[256],s1[256],s2[256]; char delim[] = "/"; char *channel; char *sidflg; len = sizeof(peer_sin); connected_socket = accept(listening_socket, (struct sockaddr *)&peer_sin, &len); if ( connected_socket == -1 ) { perror("accept"); exit(1); } int error; char hbuf[NI_MAXHOST], nhbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; error = getnameinfo((struct sockaddr *)&peer_sin, sizeof(peer_sin), hbuf, sizeof(hbuf), NULL, 0, 0); if (error) { fprintf(stderr, "getnameinfo(): %s\n", gai_strerror(error)); exit(1); } error = getnameinfo((struct sockaddr *)&peer_sin, sizeof(peer_sin), nhbuf, sizeof(nhbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV); if (error) { fprintf(stderr, "getnameinfo(): %s\n", gai_strerror(error)); exit(1); } fprintf(stderr,"connect from: %s [%s] port %s\n", hbuf, nhbuf, sbuf); read_size = read_line(connected_socket, buffer); fprintf(stderr, "request command is %s\n", buffer); // ex:GET /C8/333 HTTP/1.1 sscanf(buffer, "%s%s%s", s0, s1, s2); channel = strtok(s1, delim); if (channel != NULL) { fprintf(stderr, "Channel: %s\n", channel); parseChannel(&args, channel); sidflg = strtok(NULL, delim); if (sidflg != NULL) { fprintf(stderr, "SID: %s\n", sidflg); #ifdef TSSL args.splitter = true; args.sid_list = sidflg; } else { args.splitter = false; args.sid_list = NULL; #endif /* defined(TSSL) */ } } char header[] = "HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream\r\nCache-Control: no-cache\r\n\r\n"; write(connected_socket, header, strlen(header)); //set write target to http dest = connected_socket; } #endif /* defined(HTTP) */ #ifdef B25 // B25初期化 B25Decoder b25dec; if (args.b25) { try { b25dec.setRound(args.round); b25dec.setStrip(args.strip); b25dec.setEmmProcess(args.emm); b25dec.open(); log << "B25Decoder initialized." << std::endl; } catch (b25_error& e) { std::cerr << e.what() << std::endl; #ifdef HTTP if (!args.http_mode) { #endif /* defined(HTTP) */ // エラー時b25を行わず処理続行。終了ステータス1 std::cerr << "disable b25 decoding." << std::endl; args.b25 = false; result = 1; #ifdef HTTP } #endif /* defined(HTTP) */ } } #endif /* defined(B25) */ #ifdef UDP // UDP初期化 if( ! args.ip.empty() ){ try{ udp.setLog(&log); udp.init( args.ip, args.port ); } catch( const char* e ){ log << e << std::endl; log << "disable UDP." << std::endl; } } #endif /* defined(UDP) */ #ifdef TSSL /* initialize splitter */ splitbuf_t splitbuf; splitbuf.size = 0; splitter *splitter = NULL; int split_select_finish = TSS_ERROR; int code; if(args.splitter) { splitter = split_startup(args.sid_list); if(splitter->sid_list == NULL) { fprintf(stderr, "Cannot start TS splitter\n"); return 1; } } #endif /* defined(TSSL) */ // Tuner取得 tuner.reset(createRecordable(args.type)); #ifdef HDUS if( args.type == TUNER_HDUS ) log << "Tuner type is HDUS." << std::endl; else if( args.type == TUNER_HDP ) log << "Tuner type is HDP." << std::endl; #endif /* defined(HDUS) */ // ログ出力先設定 tuner->setLog(&log); // ロックファイル設定 if (args.lockfile != NULL) { tuner->setDetectLockFile(args.lockfile); } // Tuner初期化 int retryCount = ERROR_RETRY_MAX; while (0 < retryCount) { try { // チューナopen bool r = tuner->open(args.lnb); if (!r) { std::cerr << "can't open tuner." << std::endl; exit(1); } // チャンネル設定 tuner->setChannel(args.band, args.channel); // 開始時SignalLevel出力 float lev_before = 0.0; int lev_retry_count = SIGNALLEVEL_RETRY_MAX; while (lev_before < SIGNALLEVEL_RETRY_THRESHOLD && 0 < lev_retry_count) { lev_before = tuner->getSignalLevel(); log << "Signal level: " << lev_before << std::endl; lev_retry_count--; usleep(SIGNALLEVEL_RETRY_INTERVAL * 1000); } } catch (usb_error& e) { // リトライ処理 retryCount--; std::cerr << e.what(); if (retryCount <= 0) { std::cerr << " abort." << std::endl; exit(1); } std::cerr << " retry." << std::endl; tuner->close(); usleep(ERROR_RETRY_INTERVAL * 1000); continue; } break; } #ifndef HTTP // 出力先ファイルオープン FILE *dest = stdout; if (!args.stdout) { dest = fopen(args.destfile, "w"); if (NULL == dest) { std::cerr << "can't open file '" << args.destfile << "' to write." << std::endl; exit(1); } } #endif /* !defined(HTTP) */ // 出力開始/時間計測 log << "Output ts file." << std::endl; if (gettimeofday(&tv_start, NULL) < 0) { std::cerr << "gettimeofday failed." << std::endl; exit(1); } // SIGINT/SIGTERMキャッチ struct sigaction sa; memset(&sa, 0, sizeof(struct sigaction)); sa.sa_handler = sighandler; sa.sa_flags = SA_RESTART; struct sigaction saDefault; memset(&saDefault, 0, sizeof(struct sigaction)); saDefault.sa_handler = SIG_DFL; sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); sigaction(SIGPIPE, &sa, NULL); uint8_t *buf = NULL; int rlen; // 受信スレッド起動 tuner->startStream(); // データ読み出し uint32_t urb_error_cnt = 0; while (!caughtSignal && (args.forever || time(NULL) <= time_start + args.recsec)) { try { rlen = tuner->getStream((const uint8_t **)&buf, 200); if (0 == rlen) { continue; } #ifdef B25 // B25を経由させる。 if (args.b25) { static int f_b25_sync = 0; try { uint8_t *b25buf; b25dec.put(buf, rlen); rlen = b25dec.get((const uint8_t **)&b25buf); if (0 == rlen) { continue; } f_b25_sync = 1; buf = b25buf; } catch (b25_error& e) { if( f_b25_sync == 0 && args.sync ){ log << "Wait for B25 sync" << std::endl; continue; } log << "B25 Error: " << e.what() << std::endl; log << "Continue recording without B25." << std::endl; #ifdef HTTP if (!args.http_mode) { #endif /* defined(HTTP) */ // b25停止、戻り値エラー args.b25 = false; result = 1; #ifdef HTTP } #endif /* defined(HTTP) */ } } #endif /* defined(B25) */ #ifdef TSSL if (args.splitter) { splitbuf.size = 0; while (rlen) { /* 分離対象PIDの抽出 */ if (split_select_finish != TSS_SUCCESS) { split_select_finish = split_select(splitter, buf, rlen); if (split_select_finish == TSS_NULL) { /* mallocエラー発生 */ log << "split_select malloc failed" << std::endl; args.splitter = false; result = 1; goto fin; } else if (split_select_finish != TSS_SUCCESS) { // 分離対象PIDが完全に抽出できるまで出力しない // 1秒程度余裕を見るといいかも time_t cur_time; time(&cur_time); if (cur_time - time_start > 4) { args.splitter = false; result = 1; goto fin; } break; } } /* 分離対象以外をふるい落とす */ code = split_ts(splitter, buf, rlen, &splitbuf); if (code != TSS_SUCCESS) { log << "split_ts failed" << std::endl; break; } break; } rlen = splitbuf.size; buf = splitbuf.buffer; fin: ; } #endif /* defined(TSSL) */ #ifdef UDP // UDP 配信 udp.send(buf, rlen); #endif /* defined(UDP) */ #ifdef HTTP while(rlen > 0) { ssize_t wc; int ws = rlen < SIZE_CHUNK ? rlen : SIZE_CHUNK; while(ws > 0) { wc = write(dest, buf, ws); if(wc < 0) { log << "write failed." << std::endl; rlen = 0; buf = NULL; break; } ws -= wc; rlen -= wc; buf += wc; } } #else fwrite(buf, 1, rlen, dest); #endif /* defined(HTTP) */ } catch (usb_error& e) { if (urb_error_cnt <= URB_ERROR_MAX) { log << e.what() << std::endl; if (urb_error_cnt == URB_ERROR_MAX) { log << "Too many URB error." << std::endl; } urb_error_cnt++; } } } if (caughtSignal) { #ifdef HTTP if( args.http_mode ) caughtSignal = false; else #endif /* defined(HTTP) */ log << "interrupted." << std::endl; } // 受信スレッド停止 tuner->stopStream(); // シグナルハンドラを戻す。 sigaction(SIGINT, &saDefault, NULL); sigaction(SIGTERM, &saDefault, NULL); sigaction(SIGPIPE, &saDefault, NULL); rlen = 0; buf = NULL; #ifdef B25 // B25デコーダ内のデータを出力する。 if (args.b25) { try { b25dec.flush(); rlen = b25dec.get((const uint8_t **)&buf); } catch (b25_error& e) { log << "B25 Error: " << e.what() << std::endl; result = 1; } } #endif /* defined(B25) */ #ifdef TSSL if (args.splitter) { splitbuf.size = 0; while (rlen) { /* 分離対象PIDの抽出 */ if (split_select_finish != TSS_SUCCESS) { split_select_finish = split_select(splitter, buf, rlen); if (split_select_finish == TSS_NULL) { /* mallocエラー発生 */ log << "split_select malloc failed" << std::endl; args.splitter = false; result = 1; break; } else if (split_select_finish != TSS_SUCCESS) { // 分離対象PIDが完全に抽出できるまで出力しない // 1秒程度余裕を見るといいかも time_t cur_time; time(&cur_time); if (cur_time - time_start > 4) { args.splitter = false; result = 1; } break; } } /* 分離対象以外をふるい落とす */ code = split_ts(splitter, buf, rlen, &splitbuf); if (code != TSS_SUCCESS) { log << "split_ts failed" << std::endl; break; } break; } rlen = splitbuf.size; buf = splitbuf.buffer; split_shutdown(splitter); } #endif /* defined(TSSL) */ #ifdef HTTP while(rlen > 0) { ssize_t wc; int ws = rlen < SIZE_CHUNK ? rlen : SIZE_CHUNK; while(ws > 0) { wc = write(dest, buf, ws); if(wc < 0) { log << "write failed." << std::endl; rlen = 0; buf = NULL; break; } ws -= wc; rlen -= wc; buf += wc; } } if( args.http_mode ){ /* close http socket */ close(dest); fprintf(stderr,"connection closed. still listening at port %d\n", args.http_port); }else break; } #else if (0 < rlen) { fwrite(buf, 1, rlen, dest); } #endif /* defined(HTTP) */ // 時間計測 timeval tv_end; if (gettimeofday(&tv_end, NULL) < 0) { err(1, "gettimeofday failed."); } // 出力先ファイルクローズ #ifdef HTTP if (!args.stdout) { close(dest); } #else fflush(dest); if (!args.stdout) { fclose(dest); } #endif /* defined(HTTP) */ log << "done." << std::endl; #ifdef UDP // UDP クローズ udp.shutdown(); #endif /* defined(UDP) */ // 録画時間出力 timeval rec_time; timersub(&tv_end, &tv_start, &rec_time); log << "Rec time: " << rec_time.tv_sec << "." << std::setfill('0') << std::setw(6) << rec_time.tv_usec << " sec." << std::endl; // 終了時SignalLevel出力 try { float lev_after = tuner->getSignalLevel(); log << "Signal level: " << lev_after << std::endl; } catch (usb_error& e) { log << e.what() << " ignored." << std::endl; } return result; }
void Tuner(int argc, char* argv[]) { constexpr auto kSeed = 42; // fixed seed for reproducibility // Sets the parameters and platform/device for which to tune (command-line options) auto command_line_args = RetrieveCommandLineArguments(argc, argv); auto help = std::string{"* Options given/available:\n"}; auto args = Arguments<T>{}; args.platform_id = GetArgument(command_line_args, help, kArgPlatform, ConvertArgument(std::getenv("CLBLAST_PLATFORM"), size_t{0})); args.device_id = GetArgument(command_line_args, help, kArgDevice, ConvertArgument(std::getenv("CLBLAST_DEVICE"), size_t{0})); args.precision = GetArgument(command_line_args, help, kArgPrecision, Precision::kSingle); for (auto &o: C::GetOptions()) { if (o == kArgM) { args.m = GetArgument(command_line_args, help, kArgM, C::DefaultM()); } if (o == kArgN) { args.n = GetArgument(command_line_args, help, kArgN, C::DefaultN()); } if (o == kArgK) { args.k = GetArgument(command_line_args, help, kArgK, C::DefaultK()); } if (o == kArgAlpha) { args.alpha = GetArgument(command_line_args, help, kArgAlpha, GetScalar<T>()); } if (o == kArgBeta) { args.beta = GetArgument(command_line_args, help, kArgBeta, GetScalar<T>()); } if (o == kArgFraction) { args.fraction = GetArgument(command_line_args, help, kArgFraction, C::DefaultFraction()); } if (o == kArgBatchCount) { args.batch_count = GetArgument(command_line_args, help, kArgBatchCount, C::DefaultBatchCount()); } if (o == tStrategy) {args.tStrategy = GetArgument(command_line_args, help, tStrategy, DEFAULT_STRATEGY); } if (o == psoSwarmSize) {args.psoSwarmSize = GetArgument(command_line_args, help, psoSwarmSize, DEFAULT_PSO_SWARM); } if (o == psoInfG) {args.psoInfG = GetArgument(command_line_args, help, psoInfG, DEFAULT_PSO_G); } if (o == psoInfL) {args.psoInfL = GetArgument(command_line_args, help, psoInfL, DEFAULT_PSO_L); } if (o == psoInfR) {args.psoInfR = GetArgument(command_line_args, help, psoInfR, DEFAULT_PSO_R); } } const auto num_runs = GetArgument(command_line_args, help, kArgNumRuns, C::DefaultNumRuns()); fprintf(stdout, "%s\n", help.c_str()); // Tests validity of the given arguments C::TestValidArguments(args); // Tests for validity of the precision and retrieves properties auto isAMD = false; auto isARM = false; auto isGPU = false; { const auto platform = Platform(args.platform_id); const auto device = Device(platform, args.device_id); if (!PrecisionSupported<T>(device)) { printf("* Unsupported precision, skipping this tuning run\n\n"); return; } isAMD = device.IsAMD(); isARM = device.IsARM(); isGPU = device.IsGPU(); } // Creates input buffers with random data auto x_vec = std::vector<T>(C::GetSizeX(args)); auto y_vec = std::vector<T>(C::GetSizeY(args)); auto a_mat = std::vector<T>(C::GetSizeA(args)); auto b_mat = std::vector<T>(C::GetSizeB(args)); auto c_mat = std::vector<T>(C::GetSizeC(args)); auto temp = std::vector<T>(C::GetSizeTemp(args)); std::mt19937 mt(kSeed); std::uniform_real_distribution<double> dist(kTestDataLowerLimit, kTestDataUpperLimit); PopulateVector(x_vec, mt, dist); PopulateVector(y_vec, mt, dist); PopulateVector(a_mat, mt, dist); PopulateVector(b_mat, mt, dist); PopulateVector(c_mat, mt, dist); PopulateVector(temp, mt, dist); // Initializes the tuner for the chosen device cltune::Tuner tuner(args.platform_id, args.device_id); // Use full-search to explore all parameter combinations or random-search to search only a part of // the parameter values. The fraction is set as a command-line argument. #ifdef XGEMM_EXEC if(tStrategyFlag) { auto localtStrategy = args.tStrategy; if (args.fraction == 1.0 || args.fraction == 0.0) { localtStrategy = FULL_SEARCH_STRATEGY; } switch (localtStrategy) { case FULL_SEARCH_STRATEGY: tuner.UseFullSearch(); break; case RANDOM_SEARCH_STRATEGY: tuner.UseRandomSearch(1.0/args.fraction); break; case PSO_STRATEGY: tuner.UsePSO(1.0/args.fraction, args.psoSwarmSize, args.psoInfG, args.psoInfL, args.psoInfR); break; case DVDT_STRATEGY: default: tuner.UseFullSearch(); } } #else if (args.fraction == 1.0 || args.fraction == 0.0) { tuner.UseFullSearch(); } else { tuner.UseRandomSearch(1.0/args.fraction); } #endif // Set extra settings for specific defines. This mimics src/routine.cc. auto defines = std::string{""}; if (isAMD && isGPU) { defines += "#define USE_CL_MAD 1\n"; defines += "#define USE_STAGGERED_INDICES 1\n"; } if (isARM && isGPU) { defines += "#define GLOBAL_MEM_FENCE 1\n"; } // Loads the kernel sources and defines the kernel to tune auto sources = defines + C::GetSources(); auto id = tuner.AddKernelFromString(sources, C::KernelName(), C::GlobalSize(args), C::LocalSize()); tuner.SetReferenceFromString(sources, C::KernelName(), C::GlobalSizeRef(args), C::LocalSizeRef()); // Sets the tunable parameters and their possible values C::SetParameters(tuner, id); C::SetConstraints(tuner, id); C::SetLocalMemorySize(tuner, id, args); // Tests for a specific precision tuner.AddParameter(id, "PRECISION", {static_cast<size_t>(args.precision)}); tuner.AddParameterReference("PRECISION", static_cast<size_t>(args.precision)); // Modifies the thread-sizes (both global and local) based on the parameters for (auto ¶meters: C::MulLocal()) { tuner.MulLocalSize(id, parameters); } for (auto ¶meters: C::DivLocal()) { tuner.DivLocalSize(id, parameters); } for (auto ¶meters: C::MulGlobal()) { tuner.MulGlobalSize(id, parameters); } for (auto ¶meters: C::DivGlobal()) { tuner.DivGlobalSize(id, parameters); } // Sets the function's arguments C::SetArguments(tuner, args, x_vec, y_vec, a_mat, b_mat, c_mat, temp); // Starts the tuning process tuner.SetNumRuns(num_runs); tuner.Tune(); // Prints the results to screen auto time_ms = tuner.PrintToScreen(); tuner.PrintFormatted(); // Also prints the performance of the best-case in terms of GB/s or GFLOPS if (time_ms != 0.0) { printf("[ -------> ] %.2lf ms", time_ms); printf(" or %.1lf %s\n", C::GetMetric(args)/(time_ms*1.0e6), C::PerformanceUnit().c_str()); } // Outputs the results as JSON to disk, including some meta-data auto precision_string = std::to_string(static_cast<size_t>(args.precision)); auto metadata = std::vector<std::pair<std::string,std::string>>{ {"kernel_family", C::KernelFamily()}, {"precision", precision_string} }; for (auto &o: C::GetOptions()) { if (o == kArgM) { metadata.push_back({"arg_m", std::to_string(args.m)}); } if (o == kArgN) { metadata.push_back({"arg_n", std::to_string(args.n)}); } if (o == kArgK) { metadata.push_back({"arg_k", std::to_string(args.k)}); } if (o == kArgAlpha) { metadata.push_back({"arg_alpha", ToString(args.alpha)}); } if (o == kArgBeta) { metadata.push_back({"arg_beta", ToString(args.beta)}); } if (o == kArgBatchCount) { metadata.push_back({"arg_batch_count", ToString(args.batch_count)}); } } tuner.PrintJSON("clblast_"+C::KernelFamily()+"_"+precision_string+".json", metadata); }