Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempt to make PRPLL compatible with AutoPrimeNet #316

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 15 additions & 25 deletions src/Args.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,10 @@ and should be able to run.


Worktodo:
PRPLL keeps the active tasks in per-worker files worktodo-0.txt, worktodo-1.txt etc in the local directory.
These per-worker files are supplied from the global worktodo.txt file if -pool is used.
In turn the global worktodo.txt can be supplied through the primenet.py script,
either the one located at gpuowl/tools/primenet.py or https://download.mersenne.ca/primenet.py

It is also possible to manually add exponents by adding lines of the form "PRP=118063003" to worktodo-<N>.txt
PRPLL keeps the active tasks in worktodo.txt files in per-worker directories: worker-0, worker-1 etc.
Per-worker worktodo.txt can be supplied through the primenet.py script, either the one located at
gpuowl/tools/primenet.py or https://download.mersenne.ca/primenet.py
It is possible to manually add exponents by adding lines of the form "PRP=118063003" to worktodo.txt


The configuration options listed below can be passed on the command line or can be put in a file
Expand All @@ -130,9 +128,6 @@ named "config.txt" in the prpll run directory.
-h : print general help, list of FFTs, list of devices
-info <fft> : print detailed information about the given FFT; e.g. -h 1K:13:256
-dir <folder> : specify local work directory (containing worktodo.txt, results.txt, config.txt, gpuowl.log)
-pool <dir> : specify a directory with the shared (pooled) worktodo.txt and results.txt
Multiple PRPLL instances, each in its own directory, can share a pool of assignments and report
the results back to the common pool.
-verbose : print more log, useful for developers
-version : print only the version and exit
-user <name> : specify the mersenne.org user name (for result reporting)
Expand Down Expand Up @@ -350,13 +345,6 @@ void Args::parse(const string& line) {
}
verifyPath = s;
}
else if (key == "-pool") {
masterDir = s;
if (!masterDir.is_absolute()) {
log("-pool <path> requires an absolute path\n");
throw("-pool <path> requires an absolute path");
}
}
else if (key == "-results") { resultsFile = s; }
else if (key == "-maxAlloc" || key == "-maxalloc") {
assert(!s.empty());
Expand Down Expand Up @@ -408,15 +396,17 @@ void Args::parse(const string& line) {
void Args::setDefaults() {
uid = getUidFromPos(device);
log("device %d, OpenCL %s, unique id '%s'\n", device, getDriverVersionByPos(device).c_str(), uid.c_str());

if (!masterDir.empty()) {
assert(masterDir.is_absolute());
for (filesystem::path* p : {&proofResultDir, &proofToVerifyDir, &cacheDir, &resultsFile}) {
if (p->is_relative()) { *p = masterDir / *p; }
}
}

for (auto& p : {proofResultDir, proofToVerifyDir, cacheDir}) { fs::create_directory(p); }
fs::create_directory(cacheDir);

for (u32 i = 0; i < workers; ++i) {
fs::path worker = "worker-" + to_string(i);
fs::create_directory(worker);

fs::create_directory(worker / proofResultDir);
fs::create_directory(worker / proofToVerifyDir);

File::openAppend(worker / resultsFile); // verify that it's possible to write results
}

File::openAppend(resultsFile); // verify that it's possible to write results
}
1 change: 0 additions & 1 deletion src/Args.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ class Args {
bool useCache = false;
bool profile = false;

fs::path masterDir;
fs::path proofResultDir = "proof";
fs::path proofToVerifyDir = "proof-tmp";
fs::path cacheDir = "kernel-cache";
Expand Down
43 changes: 22 additions & 21 deletions src/Gpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1132,13 +1132,14 @@ void Gpu::doDiv9(u32 E, Words& words) {
doDiv3(E, words);
}

fs::path Gpu::saveProof(const Args& args, const ProofSet& proofSet) {
fs::path Gpu::saveProof(const Args& args, const ProofSet& proofSet, u32 instance) {
for (int retry = 0; retry < 2; ++retry) {
auto [proof, hashes] = proofSet.computeProof(this);
fs::path tmpFile = proof.file(args.proofToVerifyDir);
fs::path worker = "worker-" + to_string(instance);
fs::path tmpFile = proof.file(worker / args.proofToVerifyDir);
proof.save(tmpFile);

fs::path proofFile = proof.file(args.proofResultDir);
fs::path proofFile = proof.file(worker / args.proofResultDir);

bool ok = Proof::load(tmpFile).verify(this, hashes);
log("Proof '%s' verification %s\n", tmpFile.string().c_str(), ok ? "OK" : "FAILED");
Expand Down Expand Up @@ -1175,8 +1176,8 @@ PRPState Gpu::loadPRP(Saver<PRPState>& saver) {
throw "Error on load";
}

u32 Gpu::getProofPower(u32 k) {
u32 power = ProofSet::effectivePower(E, args.getProofPow(E), k);
u32 Gpu::getProofPower(u32 k, u32 instance) {
u32 power = ProofSet::effectivePower(E, args.getProofPow(E), k, instance);

if (power != args.getProofPow(E)) {
log("Proof using power %u (vs %u)\n", power, args.getProofPow(E));
Expand Down Expand Up @@ -1381,7 +1382,7 @@ double Gpu::timePRP() {
return secsPerIt * 1e6;
}

PRPResult Gpu::isPrimePRP(const Task& task) {
PRPResult Gpu::isPrimePRP(const Task& task, u32 instance) {
const constexpr u32 LOG_STEP = 20'000; // log every 20k its
assert(E == task.exponent);

Expand All @@ -1398,7 +1399,7 @@ PRPResult Gpu::isPrimePRP(const Task& task) {
double elapsedBefore = 0;

{
PRPState state = loadPRP(*getSaver());
PRPState state = loadPRP(*getSaver(instance));
nErrors = std::max(nErrors, state.nErrors);
blockSize = state.blockSize;
k = state.k;
Expand All @@ -1410,9 +1411,9 @@ PRPResult Gpu::isPrimePRP(const Task& task) {
u32 checkStep = checkStepForErrors(blockSize, nErrors);
assert(checkStep % LOG_STEP == 0);

u32 power = getProofPower(k);
u32 power = getProofPower(k, instance);

ProofSet proofSet{E, power};
ProofSet proofSet{E, power, instance};

bool isPrime = false;

Expand Down Expand Up @@ -1472,7 +1473,7 @@ PRPResult Gpu::isPrimePRP(const Task& task) {
++nErrors;
goto reload;
}
(*background)([=, E=this->E] { ProofSet::save(E, power, k, compactBits(rawData, E)); });
(*background)([=, E=this->E] { ProofSet::save(E, power, k, compactBits(rawData, E), instance); });
persistK = proofSet.next(k);
}

Expand Down Expand Up @@ -1510,8 +1511,8 @@ PRPResult Gpu::isPrimePRP(const Task& task) {

if (!doCheck) {
(*background)([=, this] {
getSaver()->saveUnverified({E, k, blockSize, res, compactBits(rawCheck, E), nErrors,
elapsedBefore + elapsedTimer.at()});
getSaver(instance)->saveUnverified({E, k, blockSize, res, compactBits(rawCheck, E), nErrors,
elapsedBefore + elapsedTimer.at()});
});

log(" %9u %016" PRIx64 " %4.0f\n", k, res, /*k / float(kEndEnd) * 100*,*/ secsPerIt * 1'000'000);
Expand All @@ -1532,14 +1533,14 @@ PRPResult Gpu::isPrimePRP(const Task& task) {

if (k < kEnd) {
(*background)([=, this, rawCheck = std::move(rawCheck)] {
getSaver()->save({E, k, blockSize, res, compactBits(rawCheck, E), nErrors, elapsedBefore + elapsedTimer.at()});
getSaver(instance)->save({E, k, blockSize, res, compactBits(rawCheck, E), nErrors, elapsedBefore + elapsedTimer.at()});
});
}

doBigLog(k, res, ok, secsPerIt, kEndEnd, nErrors);

if (k >= kEndEnd) {
fs::path proofFile = saveProof(args, proofSet);
fs::path proofFile = saveProof(args, proofSet, instance);
return {isPrime, finalRes64, nErrors, proofFile.string(), toHex(res2048)};
}
} else {
Expand Down Expand Up @@ -1569,13 +1570,13 @@ PRPResult Gpu::isPrimePRP(const Task& task) {
}
}

LLResult Gpu::isPrimeLL(const Task& task) {
LLResult Gpu::isPrimeLL(const Task& task, u32 instance) {
assert(E == task.exponent);
wantROE = 0;

Timer elapsedTimer;

Saver<LLState> saver{E, 1000, args.nSavefiles};
Saver<LLState> saver{E, 1000, args.nSavefiles, instance};

reload:
elapsedTimer.reset();
Expand Down Expand Up @@ -1715,15 +1716,15 @@ array<u64, 4> Gpu::isCERT(const Task& task) {
}


void Gpu::clear(bool isPRP) {
void Gpu::clear(bool isPRP, u32 instance) {
if (isPRP) {
Saver<PRPState>::clear(E);
Saver<PRPState>::clear(E, instance);
} else {
Saver<LLState>::clear(E);
Saver<LLState>::clear(E, instance);
}
}

Saver<PRPState> *Gpu::getSaver() {
if (!saver) { saver = make_unique<Saver<PRPState>>(E, args.blockSize, args.nSavefiles); }
Saver<PRPState> *Gpu::getSaver(u32 instance) {
if (!saver) { saver = make_unique<Saver<PRPState>>(E, args.blockSize, args.nSavefiles, instance); }
return saver.get();
}
12 changes: 6 additions & 6 deletions src/Gpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ class Gpu {

void modMul(Buffer<int>& ioA, Buffer<int>& inB, bool mul3 = false);

fs::path saveProof(const Args& args, const ProofSet& proofSet);
fs::path saveProof(const Args& args, const ProofSet& proofSet, u32 instance);
std::pair<RoeInfo, RoeInfo> readROE();
RoeInfo readCarryStats();

Expand All @@ -260,16 +260,16 @@ class Gpu {

~Gpu();

PRPResult isPrimePRP(const Task& task);
LLResult isPrimeLL(const Task& task);
PRPResult isPrimePRP(const Task& task, u32 instance);
LLResult isPrimeLL(const Task& task, u32 instance);
array<u64, 4> isCERT(const Task& task);

double timePRP();

tuple<bool, u64, RoeInfo, RoeInfo> measureROE(bool quick);
tuple<bool, RoeInfo> measureCarry();

Saver<PRPState> *getSaver();
Saver<PRPState> *getSaver(u32 instance);

void carryA(Buffer<double>& a, Buffer<double>& b) { carryA(reinterpret_cast<Buffer<int>&>(a), b); }

Expand Down Expand Up @@ -314,9 +314,9 @@ class Gpu {
Words expExp2(const Words& A, u32 n);
vector<Buffer<i32>> makeBufVector(u32 size);

void clear(bool isPRP);
void clear(bool isPRP, u32 instance);

private:
u32 getProofPower(u32 k);
u32 getProofPower(u32 k, u32 instance);
void doBigLog(u32 k, u64 res, bool checkOK, float secsPerIt, u32 nIters, u32 nErrors);
};
26 changes: 13 additions & 13 deletions src/Proof.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,16 @@ bool Proof::verify(Gpu *gpu, const vector<u64>& hashes) const {

// ---- ProofSet ----

ProofSet::ProofSet(u32 E, u32 power)
: E{E}, power{power} {
ProofSet::ProofSet(u32 E, u32 power, u32 instance)
: E{E}, power{power}, instance{instance} {

assert(E & 1); // E is supposed to be prime
if (power <= 0 || power > 12) {
log("Invalid proof power: %u\n", power);
throw "Invalid proof power";
}

fs::create_directories(proofPath(E));
fs::create_directories(proofPath(E, instance));

vector<u32> spans;
for (u32 span = (E + 1) / 2; spans.size() < power; span = (span + 1) / 2) { spans.push_back(span); }
Expand Down Expand Up @@ -179,9 +179,9 @@ bool ProofSet::isInPoints(u32 E, u32 power, u32 k) {
return false;
}

bool ProofSet::canDo(u32 E, u32 power, u32 currentK) {
bool ProofSet::canDo(u32 E, u32 power, u32 currentK, u32 instance) {
assert(power > 0 && power <= 12);
return ProofSet{E, power}.isValidTo(currentK);
return ProofSet{E, power, instance}.isValidTo(currentK);
}

u32 ProofSet::bestPower(u32 E) {
Expand All @@ -205,16 +205,16 @@ double ProofSet::diskUsageGB(u32 E, u32 power) {
return power ? ldexp(E, -33 + int(power)) * 1.05 : 0.0;
}

u32 ProofSet::effectivePower(u32 E, u32 power, u32 currentK) {
u32 ProofSet::effectivePower(u32 E, u32 power, u32 currentK, u32 instance) {
for (u32 p = power; p > 0; --p) {
// log("validating proof residues for power %u\n", p);
if (canDo(E, p, currentK)) { return p; }
if (canDo(E, p, currentK, instance)) { return p; }
}
return 0;
}

bool ProofSet::fileExists(u32 k) const {
return File::size(proofPath(E) / to_string(k)) == i64(E / 32 + 2) * 4;
return File::size(proofPath(E, instance) / to_string(k)) == i64(E / 32 + 2) * 4;
}

bool ProofSet::isValidTo(u32 limitK) const {
Expand Down Expand Up @@ -245,18 +245,18 @@ u32 ProofSet::next(u32 k) const {
return *cacheIt;
}

void ProofSet::save(u32 E, u32 power, u32 k, const Words& words) {
void ProofSet::save(u32 E, u32 power, u32 k, const Words& words, u32 instance) {
assert(k && k <= E);
assert(isInPoints(E, power, k));

File::openWrite(proofPath(E) / to_string(k)).writeChecked(words);
assert(load(E, power, k) == words);
File::openWrite(proofPath(E, instance) / to_string(k)).writeChecked(words);
assert(load(E, power, k, instance) == words);
}

Words ProofSet::load(u32 E, u32 power, u32 k) {
Words ProofSet::load(u32 E, u32 power, u32 k, u32 instance) {
assert(k && k <= E);
assert(isInPoints(E, power, k));
return File::openReadThrow(proofPath(E) / to_string(k)).readChecked<u32>(E/32 + 1);
return File::openReadThrow(proofPath(E, instance) / to_string(k)).readChecked<u32>(E/32 + 1);
}

std::pair<Proof, vector<u64>> ProofSet::computeProof(Gpu *gpu) const {
Expand Down
20 changes: 12 additions & 8 deletions src/Proof.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,35 +55,39 @@ class ProofSet {
public:
const u32 E;
const u32 power;
const u32 instance;

private:
vector<u32> points;

bool isValidTo(u32 limitK) const;

static bool canDo(u32 E, u32 power, u32 currentK);
static bool canDo(u32 E, u32 power, u32 currentK, u32 instance);

mutable decltype(points)::const_iterator cacheIt{};

bool fileExists(u32 k) const;

static fs::path proofPath(u32 E) { return fs::path(to_string(E)) / "proof"; }
static fs::path proofPath(u32 E, u32 instance) {
fs::path worker = "worker-" + to_string(instance);
return fs::path(worker / to_string(E)) / "proof";
}
public:

static u32 bestPower(u32 E);
static u32 effectivePower(u32 E, u32 power, u32 currentK);
static u32 effectivePower(u32 E, u32 power, u32 currentK, u32 instance);
static double diskUsageGB(u32 E, u32 power);
static bool isInPoints(u32 E, u32 power, u32 k);

ProofSet(u32 E, u32 power);
ProofSet(u32 E, u32 power, u32 instance);

u32 next(u32 k) const;

static void save(u32 E, u32 power, u32 k, const Words& words);
static Words load(u32 E, u32 power, u32 k);
static void save(u32 E, u32 power, u32 k, const Words& words, u32 instance);
static Words load(u32 E, u32 power, u32 k, u32 instance);

void save(u32 k, const Words& words) const { return save(E, power, k, words); }
Words load(u32 k) const { return load(E, power, k); }
void save(u32 k, const Words& words) const { return save(E, power, k, words, instance); }
Words load(u32 k) const { return load(E, power, k, instance); }


std::pair<Proof, vector<u64>> computeProof(Gpu *gpu) const;
Expand Down
Loading