forked from preda/gpuowl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTask.cpp
173 lines (143 loc) · 5.02 KB
/
Task.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// Copyright (C) Mihai Preda.
#include "Task.h"
#include "Gpu.h"
#include "Args.h"
#include "File.h"
#include "GmpUtil.h"
#include "Worktodo.h"
#include "Saver.h"
#include "version.h"
#include "Proof.h"
#include "log.h"
#include <cstdio>
#include <cmath>
#include <thread>
#include <cassert>
namespace {
string json(const vector<string>& v) {
bool isFirst = true;
string s = "{";
for (const std::string& e : v) {
if (e.empty()) { continue; }
if (!isFirst) { s += ", "; } else { isFirst = false; }
s += e;
}
return {isFirst ? ""s : (s + '}')};
}
struct Hex {
explicit Hex(u64 value) : value{value} {}
u64 value;
};
string json(Hex x) { return '"' + hex(x.value) + '"'; }
string json(const string& s) { return '"' + s + '"'; }
string json(u32 x) { return json(to_string(x)); }
template<typename T> string json(const string& key, const T& value) { return json(key) + ':' + json(value); }
string maybe(const string& key, const string& value) { return value.empty() ? ""s : json(key, value); }
template<typename T> void operator+=(vector<T>& a, const vector<T>& b) { a.insert(a.end(), b.begin(), b.end()); }
vector<string> commonFields(u32 E, const char *worktype, const string &status) {
return {json("status", status),
json("exponent", E),
json("worktype", worktype)
};
}
vector<string> tailFields(const std::string &AID, const Args &args) {
return {json("program", vector<string>{json("name", "gpuowl"), json("version", VERSION)}),
maybe("user", args.user),
maybe("computer", args.cpu),
maybe("aid", AID),
maybe("uid", args.uid),
json("timestamp", timeStr())
};
}
void writeResult(u32 E, const char *workType, const string &status, const std::string &AID, const Args &args,
const vector<string>& extras) {
vector<string> fields = commonFields(E, workType, status);
fields += extras;
fields += tailFields(AID, args);
string s = json(std::move(fields));
log("%s\n", s.c_str());
File::append(args.resultsFile, s + '\n');
}
}
void Task::writeResultPRP(const Args &args, bool isPrime, u64 res64, u32 fftSize, u32 nErrors, const fs::path& proofPath) const {
vector<string> fields{json("res64", Hex{res64}),
json("residue-type", 1),
json("errors", vector<string>{json("gerbicz", nErrors)}),
json("fft-length", fftSize)
};
// "proof":{"version":1, "power":6, "hashsize":64, "md5":"0123456789ABCDEF"},
if (!proofPath.empty()) {
ProofInfo info = proof::getInfo(proofPath);
fields.push_back(json("proof", vector<string>{
json("version", 1),
json("power", info.power),
json("hashsize", 64),
json("md5", info.md5)
}));
}
writeResult(exponent, "PRP-3", isPrime ? "P" : "C", AID, args, fields);
}
void Task::writeResultPM1(const Args& args, const string& factor, u32 fftSize) const {
assert(B1);
bool hasFactor = !factor.empty();
u32 reportB2 = B2;
if (hasFactor) {
auto factors = factorize(factor, exponent, B1, B2);
if (factors.empty()) {
log("Error attempting to split '%s'\n", factor.c_str());
} else {
reportB2 = factors.back();
assert(reportB2 <= B2);
string fstr;
for (u32 f : factors) { fstr += ", "s + to_string(f); }
log("%s %.1f bits%s\n", factor.c_str(), log2(factor), fstr.c_str());
}
}
writeResult(exponent, "PM1", hasFactor ? "F" : "NF", AID, args,
{json("B1", B1),
(reportB2 > B1) ? json("B2", reportB2) : "",
json("fft-length", fftSize),
factor.empty() ? "" : (json("factors") + ':' + "[\""s + factor + "\"]")
});
}
void Task::adjustBounds(Args& args) {
if (kind == PRP && wantsPm1) {
if (B1 == 0 && args.B1) { B1 = args.B1; }
if (B2 == 0 && args.B2) { B2 = args.B2; }
if (B1 == 0) {
float ratio = (bitLo <= 76) ? 20 : (bitLo == 77) ? 25 : 30;
u32 step = 500'000;
B1 = u32(float(exponent) / (step * ratio) + .5f) * step;
}
if (B2 == 0) { B2 = B1 * args.B2_B1_ratio; }
if (B1 < 10000) {
log("B1=%u too small, adjusted to %u\n", B1, 10000);
B1 = 10000;
}
if (B2 < 2 * B1) {
log("B2=%u too small, adjusted to %u\n", B2, 2 * B1);
B2 = 2 * B1;
}
}
}
void Task::execute(const Args& args) {
LogContext pushContext(std::to_string(exponent));
if (kind == VERIFY) {
Proof proof = Proof::load(verifyPath);
auto gpu = Gpu::make(proof.E, args);
bool ok = proof.verify(gpu.get());
log("proof '%s' %s\n", verifyPath.c_str(), ok ? "verified" : "failed");
return;
}
assert(kind == PRP);
auto gpu = Gpu::make(exponent, args);
auto fftSize = gpu->getFFTSize();
if (kind == PRP) {
auto [factor, isPrime, res64, nErrors, proofPath] = gpu->isPrimePRP(args, *this);
if (factor.empty()) {
writeResultPRP(args, isPrime, res64, fftSize, nErrors, proofPath);
}
Worktodo::deleteTask(*this);
if (!isPrime) { Saver::cleanup(exponent, args); }
}
}