Commit e91e8cfe authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

compiler cleanup, adding hardware dependent transformations to qcor compiler


Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent ac9a8629
Pipeline #58973 passed with stages
in 7 minutes and 12 seconds
#include "QCORCompiler.hpp"
#include "IRProvider.hpp"
#include "xacc_service.hpp"
namespace qcor {
std::shared_ptr<IR> QCORCompiler::compile(const std::string &src,
std::shared_ptr<Accelerator> acc) {
return nullptr;
}
......@@ -16,19 +17,21 @@ std::shared_ptr<IR> QCORCompiler::compile(const std::string &src) {
const std::shared_ptr<Function>
QCORCompiler::compile(std::shared_ptr<Function> f, std::shared_ptr<Accelerator> acc) {
if (acc) {
// xacc::info("[qcor] Compiling for " + acc->name());
}
// Hardware Independent Transformation
auto provider = xacc::getService<xacc::IRProvider>("quantum");
auto ir = provider->createIR();
ir->addKernel(f);
// FIXME Hardware Independent Transformation
// Hardware Dependent Transformations
if (acc) {
auto ts = acc->getIRTransformations();
for (auto& t : ts) {
ir = t->transform(ir);
}
}
// Program Verification???
// FIXME Program Verification???
return f;
}
......
......@@ -30,9 +30,12 @@ bool FuzzyParsingExternalSemaSource::LookupUnqualified(clang::LookupResult &R,
// If this is a valid quantum instruction, tell Clang its
// all gonna be ok, we got this...
if (std::find(validInstructions.begin(), validInstructions.end(),
unknownName) != validInstructions.end()) {
if (std::find(validInstructions.begin(), validInstructions.end(), // not template scope
unknownName) != validInstructions.end() && S->getFlags() != 128 && S->getBlockParent() != nullptr) {
// std::cout << "HELLO FP: " << unknownName << ", " << S->getFlags() << "\n";
// S->dump();
// S->getBlockParent()->dump();
IdentifierInfo *II = Name.getAsIdentifierInfo();
SourceLocation Loc = R.getNameLoc();
auto fdecl = FunctionDecl::Create(
......
......@@ -162,8 +162,8 @@ bool LambdaVisitor::CallExprToIRGenerator::VisitInitListExpr(
ScanInitListExpr visitor;
visitor.TraverseStmt(child);
options.insert({visitor.key, visitor.value});
std::cout << "Inserting " << visitor.key << ", "
<< visitor.value.toString() << "\n";
// std::cout << "Inserting " << visitor.key << ", "
// << visitor.value.toString() << "\n";
}
keepSearching = false;
......@@ -182,7 +182,6 @@ bool LambdaVisitor::CallExprToIRGenerator::VisitDeclRefExpr(DeclRefExpr *decl) {
if (dyn_cast<ParmVarDecl>(decl->getDecl())) {
auto declName = decl->getNameInfo().getAsString();
// std::cout << "IRGENERATOR FOUND PARAM: " << declName << "\n";
options.insert({"param-id", declName});
}
return true;
......@@ -268,6 +267,7 @@ bool LambdaVisitor::ScanInitListExpr::VisitStringLiteral(
}
return true;
}
bool LambdaVisitor::ScanInitListExpr::VisitFloatingLiteral(
FloatingLiteral *literal) {
......@@ -280,6 +280,7 @@ bool LambdaVisitor::ScanInitListExpr::VisitFloatingLiteral(
}
return true;
}
bool LambdaVisitor::ScanInitListExpr::VisitIntegerLiteral(
IntegerLiteral *literal) {
......@@ -325,8 +326,8 @@ bool LambdaVisitor::VisitLambdaExpr(LambdaExpr *LE) {
// If it is, then map it to XACC IR
if (isqk.isQuantumKernel()) {
LE->dumpColor();
// LE->dumpColor();
// exit(0);
auto cb = LE->capture_begin(); // implicit_capture_begin();
auto ce = LE->capture_end();
VarDecl *v;
......@@ -386,7 +387,7 @@ bool LambdaVisitor::VisitLambdaExpr(LambdaExpr *LE) {
}
}
std::cout << "\n\nXACC IR:\n" << function->toString() << "\n";
// std::cout << "\n\nXACC IR:\n" << function->toString() << "\n";
// Check if we have IRGenerators in the tree
if (function->hasIRGenerators()) {
......
#include "QCORASTConsumer.hpp"
#include "LambdaVisitor.hpp"
#include <chrono>
// #include "clang/ASTMatchers/ASTMatchFinder.h"
// #include "clang/ASTMatchers/ASTMatchers.h"
// using namespace clang::ast_matchers;
using namespace clang;
namespace qcor {
namespace compiler {
QCORASTConsumer::QCORASTConsumer(CompilerInstance &c, Rewriter& rw)
QCORASTConsumer::QCORASTConsumer(CompilerInstance &c, Rewriter &rw)
: ci(c), fuzzyParser(std::make_shared<FuzzyParsingExternalSemaSource>(
c.getASTContext())), rewriter(rw) {}
c.getASTContext())),
rewriter(rw) {}
bool QCORASTConsumer::HandleTopLevelDecl(DeclGroupRef DR) {
using namespace std::chrono;
auto start = std::chrono::high_resolution_clock::now();
LambdaVisitor visitor(ci, rewriter);
ci.getSema().addExternalSource(fuzzyParser.get());
for (DeclGroupRef::iterator b = DR.begin(), e = DR.end(); b != e; ++b) {
// if (std::string((*b)->getDeclKindName()) == "Function") {
// std::cout << (*b)->getDeclKindName() << "\n";
// (*b)->dumpColor();
visitor.TraverseDecl(*b);
// }
}
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<microseconds>(stop - start);
// std::cout << "Visitor time: " << duration.count() << ", " << std::endl;
return true;
}
} // namespace compiler
......
......@@ -21,6 +21,8 @@
#include <fstream>
#include <string>
#include "FuzzyParsingExternalSemaSource.hpp"
#include "QCORASTConsumer.hpp"
#include "XACC.hpp"
using namespace clang;
......@@ -46,6 +48,9 @@ protected:
CI.createSema(getTranslationUnitKind(), nullptr);
rewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
qcor::compiler::FuzzyParsingExternalSemaSource source(CI.getASTContext());
CI.getSema().addExternalSource(&source);
ParseAST(CI.getSema());
CI.getDiagnosticClient().EndSourceFile();
......@@ -86,7 +91,6 @@ int main(int argc, char **argv) {
xacc::error("File " + fileName + " does not exist.");
}
std::ifstream t(fileName);
std::string src((std::istreambuf_iterator<char>(t)),
std::istreambuf_iterator<char>());
......@@ -96,10 +100,8 @@ int main(int argc, char **argv) {
auto action = new QCORFrontendAction(Rewrite, fileName);
std::vector<std::string> args{
"-std=c++11", "-I@CMAKE_INSTALL_PREFIX@/include/qcor",
"-I@CMAKE_INSTALL_PREFIX@/include/xacc",
"-I@CMAKE_INSTALL_PREFIX@/include/cppmicroservices4",
"-I@CMAKE_INSTALL_PREFIX@/include/quantum/gate"};
"-ftime-report", "-std=c++11", "-I@CMAKE_INSTALL_PREFIX@/include/qcor",
"-I@CMAKE_INSTALL_PREFIX@/include/xacc"};
if (!tooling::runToolOnCodeWithArgs(action, src, args)) {
xacc::error("Error running qcor compiler.");
......
......@@ -6,7 +6,7 @@
using namespace xacc;
namespace qcor{
namespace qcor {
namespace instructions {
bool HWE::validateOptions() {
if (options.count("n-qubits")) {
......@@ -17,23 +17,23 @@ bool HWE::validateOptions() {
return true;
}
std::shared_ptr<Function> HWE::generate(
std::shared_ptr<AcceleratorBuffer> buffer,
std::shared_ptr<Function>
HWE::generate(std::shared_ptr<AcceleratorBuffer> buffer,
std::vector<InstructionParameter> parameters) {
xacc::error("qcor::HWE::generate(buffer,params) not implemented.");
return nullptr;
}
std::shared_ptr<xacc::Function> HWE::generate(
std::map<std::string, xacc::InstructionParameter>& parameters) {
std::shared_ptr<xacc::Function>
HWE::generate(std::map<std::string, xacc::InstructionParameter> &parameters) {
if (!parameters.empty()) {
options = parameters;
}
return generate(std::map<std::string, InstructionParameter>{});
}
std::shared_ptr<Function> HWE::generate(
std::map<std::string, InstructionParameter>&& parameters ) {
std::shared_ptr<Function>
HWE::generate(std::map<std::string, InstructionParameter> &&parameters) {
if (!parameters.empty()) {
options = parameters;
......@@ -47,8 +47,8 @@ std::shared_ptr<Function> HWE::generate(
if (options.count("coupling")) {
connectivity = options["coupling"].as<std::vector<std::pair<int, int>>>();
} else {
for (int i = 0; i < nQubits-1; i++) {
connectivity.push_back({i,i+1});
for (int i = 0; i < nQubits - 1; i++) {
connectivity.push_back({i, i + 1});
}
}
......@@ -62,7 +62,7 @@ std::shared_ptr<Function> HWE::generate(
}
std::vector<InstructionParameter> fParams;
for (int nP = 0; nP < (2*nQubits + 3 * nQubits * layers); nP++)
for (int nP = 0; nP < (2 * nQubits + 3 * nQubits * layers); nP++)
fParams.push_back(InstructionParameter(paramLetter + std::to_string(nP)));
auto provider = xacc::getService<IRProvider>("gate");
......@@ -72,12 +72,14 @@ std::shared_ptr<Function> HWE::generate(
// Zeroth layer, start with X and Z rotations
for (int q = 0; q < nQubits; q++) {
auto rx = provider->createInstruction(
"Rx", {q}, {InstructionParameter(paramLetter + std::to_string(angleCounter))});
"Rx", {q},
{InstructionParameter(paramLetter + std::to_string(angleCounter))});
auto rz = provider->createInstruction(
"Rz", {q}, {InstructionParameter(paramLetter + std::to_string(angleCounter+1))});
"Rz", {q},
{InstructionParameter(paramLetter + std::to_string(angleCounter + 1))});
f->addInstruction(rx);
f->addInstruction(rz);
angleCounter+=2;
angleCounter += 2;
}
for (int d = 0; d < layers; d++) {
......@@ -93,12 +95,14 @@ std::shared_ptr<Function> HWE::generate(
auto rx = provider->createInstruction(
"Rx", {q},
{InstructionParameter(paramLetter + std::to_string(angleCounter+1))});
{InstructionParameter(paramLetter +
std::to_string(angleCounter + 1))});
f->addInstruction(rx);
auto rz2 = provider->createInstruction(
"Rz", {q},
{InstructionParameter(paramLetter + std::to_string(angleCounter + 2))});
{InstructionParameter(paramLetter +
std::to_string(angleCounter + 2))});
f->addInstruction(rz2);
angleCounter += 3;
......@@ -108,5 +112,5 @@ std::shared_ptr<Function> HWE::generate(
return f;
}
}
}
\ No newline at end of file
} // namespace instructions
} // namespace qcor
\ No newline at end of file
......@@ -54,16 +54,11 @@ Eigen::MatrixXd compute_2body_fock(const libint2::BasisSet &shells,
auto s12_34_deg = (s1 == s3) ? (s2 == s4 ? 1.0 : 2.0) : 2.0;
auto s1234_deg = s12_deg * s34_deg * s12_34_deg;
const auto tstart = std::chrono::high_resolution_clock::now();
engine.compute(shells[s1], shells[s2], shells[s3], shells[s4]);
const auto *buf_1234 = buf[0];
if (buf_1234 == nullptr)
continue; // if all integrals screened out, skip to next quartet
const auto tstop = std::chrono::high_resolution_clock::now();
time_elapsed += tstop - tstart;
for (auto f1 = 0, f1234 = 0; f1 != n1; ++f1) {
const auto bf1 = f1 + bf1_first;
for (auto f2 = 0; f2 != n2; ++f2) {
......@@ -96,11 +91,11 @@ Eigen::MatrixXd compute_2body_fock(const libint2::BasisSet &shells,
Eigen::MatrixXd Gt = G.transpose();
return 0.5 * (G + Gt);
}
void LibIntWrapper::generate(std::map<std::string, std::string> &&options) {
generate(options);
void LibIntWrapper::generate(std::map<std::string, std::string> &&options, std::vector<int> active, std::vector<int> frozen) {
generate(options, active, frozen);
}
void LibIntWrapper::generate(std::map<std::string, std::string> &options) {
void LibIntWrapper::generate(std::map<std::string, std::string> &options, std::vector<int> active, std::vector<int> frozen) {
auto basis = options["basis"];
auto geom = options["geometry"];
......@@ -137,12 +132,6 @@ void LibIntWrapper::generate(std::map<std::string, std::string> &options) {
libint2::Shell::do_enforce_unit_normalization(false);
// std::cout << "Atomic Cartesian coordinates (a.u.):" << std::endl;
// for (const auto &a : atoms) {
// std::cout << a.atomic_number << " " << a.x << " " << a.y << " " << a.z
// << std::endl;
// }
libint2::initialize();
libint2::BasisSet obs(basis, atoms, true);
......@@ -170,24 +159,19 @@ void LibIntWrapper::generate(std::map<std::string, std::string> &options) {
// const auto& is very important!
nBasis = obs.nbf();
auto nshells = obs.size();
// std::cout << "NBF: " << nBasis << "\n";
Eigen::Tensor<double,4> eri_data_t(nBasis, nBasis, nBasis, nBasis);
eri_data_t.setZero();
Eigen::Tensor<double, 1> data_(std::pow(nBasis, 4));
int ii = 0;
// std::cout << "MATRIX:\n" << result << "\n";
for (auto s1 = 0; s1 != obs.size(); ++s1) {
for (auto s2 = 0; s2 != obs.size(); ++s2) {
for (auto s3 = 0; s3 != obs.size(); ++s3) {
for (auto s4 = 0; s4 != obs.size(); ++s4) {
// std::cout << "compute shell set {" << s1 << "," << s2 << "," << s3
// << "," << s4 << "} ... ";
eri_engine.compute(obs[s1], obs[s2], obs[s3], obs[s4]);
// std::cout << "done. ";
auto ints_shellset = buf[0];
// std::cout << ii << ", " << ints_shellset[0] << "\n";
data_(ii) = ints_shellset[0];
eri_data.push_back(ints_shellset[0]);
ii++;
......@@ -196,12 +180,8 @@ void LibIntWrapper::generate(std::map<std::string, std::string> &options) {
}
}
// std::cout << "ERI Vec:\n" << data_ << "\n";
// std::cout << "obs size: " << obs.size() << "\n";
const auto &kinetic_buf_vec =
kinetic_engine.results(); // will point to computed shell sets
// const auto& is very important!
kinetic_engine.results();
Eigen::Tensor<double, 2> T(nBasis, nBasis);
for (auto s1 = 0; s1 != obs.size(); ++s1) {
......@@ -233,6 +213,7 @@ void LibIntWrapper::generate(std::map<std::string, std::string> &options) {
}
}
}
// kinetic_data =
// std::cout << "T:\n" << T << "\n";
......@@ -317,6 +298,8 @@ void LibIntWrapper::generate(std::map<std::string, std::string> &options) {
Eigen::MatrixXd H = T_ + V_;
std::cout << "T:\n" << T << "\n\n";
std::cout << "V:\n" << V << "\n\n";
Eigen::MatrixXd D;
// solve H C = e S C
Eigen::GeneralizedSelfAdjointEigenSolver<Eigen::MatrixXd> gen_eig_solver(H,
......@@ -469,15 +452,17 @@ void LibIntWrapper::generate(std::map<std::string, std::string> &options) {
Eigen::Tensor<double, 4> gmo =
tmp3.contract(CTensor, Eigen::array<IP, 1>{IP(0, 0)});
Eigen::Tensor<double, 2> H_core_ao = getAOKinetic() + getAOPotential();
Eigen::Tensor<double, 2> H_core_ao = Eigen::TensorMap<Eigen::Tensor<double,2>>(H.data(), nBasis,nBasis);
Eigen::MatrixXd H_core_ao_m =
Eigen::Map<Eigen::MatrixXd>(H_core_ao.data(), nBasis, nBasis);
// std::cout << "HCOREAO:\n" << H_core_ao << "\n\n";
Eigen::MatrixXd H_core_ao_m = H;
// Eigen::Map<Eigen::MatrixXd>(H_core_ao.data(), nBasis, nBasis);
Eigen::MatrixXd H_1body_ao(2 * nBasis, 2 * nBasis);
H_1body_ao.block(0, 0, nBasis, nBasis) = H_core_ao_m;
H_1body_ao.block(nBasis, nBasis, nBasis, nBasis) = H_core_ao_m;
std::cout << "AO:\n" << H_1body_ao << "\n\n";
Eigen::Tensor<double, 2> H_1body_ao_Tensor =
Eigen::TensorMap<Eigen::Tensor<double, 2>>(H_1body_ao.data(), 2 * nBasis,
2 * nBasis);
......@@ -492,39 +477,36 @@ void LibIntWrapper::generate(std::map<std::string, std::string> &options) {
Eigen::Tensor<double, 2> H_1body_Final =
CTensorT.contract(tmpTensor, Eigen::array<IP, 1>{IP(1, 0)});
// int c = 0;
// for (int i = 0; i < 4; i++) {
// for (int j = 0; j < 4; j++) {
// for (int k = 0; k < 4; k++) {
// for (int l = 0; l < 4; l++) {
// if (std::fabs(gmo(i,j,k,l)) > 1e-12) {
// std::cout << c << ", " << (std::fabs(gmo(i, j, k, l)) > 1e-10 ? gmo(i, j, k, l)
// : 0.0)
// << "\n";
// c++;
// }
// }
// }
// }
// }
std::vector<int> active_list(2*nBasis), frozen_list;
std::iota(active_list.begin(), active_list.end(),0);
if (!active.empty() && !frozen.empty()) {
active_list.clear();
active_list = active;
frozen_list = frozen;
for (auto& a : active_list) {
std::cout << "Active: " << a << "\n";
}
for (auto& a : frozen_list) {
std::cout << "frozen_list: " << a << "\n";
}
}
int nActive = active_list.size();
int nFrozen = 0;
int nFrozen = frozen_list.size();
// std::cout << Eigen::Map<Eigen::MatrixXd>(H_1body_Final.data(), 20,20).diagonal() << "\n";
auto tmp_enuc = enuc;
for (int i = 0; i < nFrozen; i++) {
auto ia = frozen_list[i];
for (int a = 0; a < nFrozen; a++) {
auto ia = frozen_list[a];
tmp_enuc += H_1body_Final(ia,ia);
for (int b = 0; b < i; b++) {
for (int b = 0; b < a; b++) {
auto ib = frozen_list[b];
tmp_enuc += gmo(ia,ib,ia,ib);
std::cout << ia << ", " << ib << ", " << gmo(ia,ib,ia,ib) << "\n";
}
}
std::cout << nBasis << ", TMPNUC: " << enuc << ", " << tmp_enuc << "\n";
Eigen::Tensor<double, 2> h_fc_1body(nActive,nActive); h_fc_1body.setZero();
for (int p = 0; p < nActive; p++ ){
auto ip = active_list[p];
......@@ -557,10 +539,6 @@ void LibIntWrapper::generate(std::map<std::string, std::string> &options) {
Eigen::Tensor<double, 4> tmp_shuffle = h_fc_2body.shuffle(Eigen::array<int,4>{0,1,3,2});
Eigen::Tensor<double, 4> h_fc_2body_tmp = tmp_shuffle * 0.25;
// std::cout << "One BOdy:\n"
// << Eigen::Map<Eigen::MatrixXd>(h_fc_1body.data(), 2 * nBasis,
// 2 * nBasis)
// << "\n";
_hpq = h_fc_1body;//H_1body_Final;
_hpqrs = h_fc_2body_tmp;
_e_nuc = tmp_enuc;
......
......@@ -8,8 +8,8 @@
namespace libintwrapper {
class LibIntWrapper {
public:
void generate(std::map<std::string, std::string> &&options);
void generate(std::map<std::string, std::string> &options);
void generate(std::map<std::string, std::string> &&options, std::vector<int> active = {}, std::vector<int> frozen = {});
void generate(std::map<std::string, std::string> &options, std::vector<int> active = {}, std::vector<int> frozen = {});
Eigen::Tensor<double, 2> getAOKinetic();
Eigen::Tensor<double, 2> getAOPotential();
Eigen::Tensor<double, 4> getERI();
......
#ifndef RUNTIME_QCOR_HPP_
#define RUNTIME_QCOR_HPP_
#include "optimizer.hpp"
#include <future>
#include "Observable.hpp"
#include "optimizer.hpp"
#include "algorithm.hpp"
#include "Observable.hpp"
namespace xacc {
class Function;
class AcceleratorBuffer;
class Accelerator;
class Observable;
} // namespace xacc
using namespace xacc;
......@@ -19,6 +19,7 @@ using namespace xacc;
namespace qcor {
class qpu_handler;
using HandlerLambda = std::function<void(qpu_handler &)>;
extern std::map<std::string, InstructionParameter> runtimeMap;
......
......@@ -29,6 +29,7 @@ def parse_args(args):
def main(argv=None):
opts = parse_args(sys.argv[1:])
import time
command = ["qcor-driver"]
includes = []
if opts.include:
......@@ -40,19 +41,16 @@ def main(argv=None):
if opts.accelerator:
command += ['--accelerator', opts.accelerator]
baseIncludes = ['-I', '@CMAKE_INSTALL_PREFIX@/include/xacc', '-I', '@CMAKE_INSTALL_PREFIX@/include/quantum/gate',
'-I', '@CMAKE_INSTALL_PREFIX@/include/cppmicroservices4', '-I', '@CMAKE_INSTALL_PREFIX@/include/qcor']
baseLibs = ['-L', '@CMAKE_INSTALL_PREFIX@/lib', '-lxacc',
'-lqcor', '-lCppMicroServices', '-lxacc-quantum-gate', '-lxacc-pauli']
command += [opts.file]
if opts.verbose:
command += ['-v']
print(command)
try:
s = time.time()
result = subprocess.run(command, check=True)
e = time.time()
print('time: ', (e-s))
except subprocess.CalledProcessError as e:
print(e.output)
print(e.returncode)
......@@ -60,6 +58,10 @@ def main(argv=None):
command.clear()
baseIncludes = ['-I', '@CMAKE_INSTALL_PREFIX@/include/xacc', '-I', '@CMAKE_INSTALL_PREFIX@/include/qcor']
baseLibs = ['-L', '@CMAKE_INSTALL_PREFIX@/lib', '-lxacc',
'-lqcor', '-lCppMicroServices', '-lxacc-quantum-gate', '-lxacc-pauli']
command = ['@CLANG_COMPILER@', '-std=c++11', '-Wl,-rpath,@CMAKE_INSTALL_PREFIX@/lib']
command += includes + baseIncludes + baseLibs
command += ['.' + opts.file.replace('.','_out.')]
......@@ -69,7 +71,10 @@ def main(argv=None):
print('Final command', command)
try:
s = time.time()
result = subprocess.run(command, check=True)
e = time.time()
print('final compile time: ', (e-s))
except subprocess.CalledProcessError as e:
print(e.output)
print(e.returncode)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment