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

20240925 quest capability #50

Open
wants to merge 3 commits into
base: main
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
19 changes: 19 additions & 0 deletions configuration/archer2.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,25 @@ def command(self, job):
"num_sockets": 2,
},
},
{
"name": "compute-capability",
"descr": "Compute nodes during capabilitydays",
"scheduler": "slurm",
"launcher": "srun",
"access": [
"--hint=nomultithread",
"--distribution=block:block",
"--partition=standard",
"--qos=capabilityday",
],
"environs": ["PrgEnv-gnu", "PrgEnv-cray", "PrgEnv-aocc"],
"max_jobs": 64,
"processor": {
"num_cpus": 128,
"num_cpus_per_socket": 64,
"num_sockets": 2,
},
},
{
"name": "compute-gpu",
"descr": "Compute nodes with AMD GPUs",
Expand Down
61 changes: 61 additions & 0 deletions tests/apps/quest/Quest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env python3

# Based on original work from:
# Copyright 2016-2022 Swiss National Supercomputing Centre (CSCS/ETH Zurich)
# ReFrame Project Developers. See the top-level LICENSE file for details.
# SPDX-License-Identifier: BSD-3-Clause

import reframe as rfm
import reframe.utility.sanity as sn


@rfm.simple_test
class QuestQFTTest(rfm.RegressionTest):
"""Quest 4 node Test"""

valid_systems = ["archer2:compute"]
valid_prog_environs = ["PrgEnv-gnu"]

tags = {"performance", "applications"}

num_nodes = 4
num_tasks_per_node = 1
num_cpus_per_task = 128
num_tasks = num_nodes * num_tasks_per_node

env_vars = {"OMP_NUM_THREADS": str(num_cpus_per_task), "OMP_PLACES": "cores"}

time_limit = "20m"
build_system = "Make"
prebuild_cmds = [
"git clone https://github.com/QuEST-Kit/QuEST.git",
"source cmake_questQFT.sh qft",
]
builddir = "build"
executable = "build/qft"
executable_opts = ["34"]
modules = ["cmake/3.29.4"]

@run_before("compile")
def prepare_build(self):
self.prebuild_cmd = ["git clone https://github.com/QuEST-Kit/QuEST.git .", "source cmake_questQFT.sh qft"]

@run_before("run")
def set_num_nodes(self):
self.job.options = [f"--nodes={self.num_nodes}"]

@sanity_function
def assert_finished(self):
"""Sanity check that simulation finished successfully"""
return sn.assert_found("Total run time:", self.stdout)


# @performance_function("seconds", perf_key="performance")
# def extract_perf(self):
# """Extract performance value to compare with reference value"""
# return sn.extractsingle(
# r"Averaged time per step \(s\):\s+(?P<steptime>\S+)",
# self.stdout,
# "time",
# float,
# )
61 changes: 61 additions & 0 deletions tests/apps/quest/QuestHuge.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env python3

# Based on original work from:
# Copyright 2016-2022 Swiss National Supercomputing Centre (CSCS/ETH Zurich)
# ReFrame Project Developers. See the top-level LICENSE file for details.
# SPDX-License-Identifier: BSD-3-Clause

import reframe as rfm
import reframe.utility.sanity as sn


@rfm.simple_test
class QuestQFTHugeTest(rfm.RegressionTest):
"""Quest Huge 4096 node Test"""

valid_systems = ["archer2:compute-capability"]
valid_prog_environs = ["PrgEnv-gnu"]

tags = {"performance", "largescale", "applications"}

num_nodes = 4096
num_tasks_per_node = 1
num_cpus_per_task = 128
num_tasks = num_nodes * num_tasks_per_node

env_vars = {"OMP_NUM_THREADS": str(num_cpus_per_task), "OMP_PLACES": "cores"}

time_limit = "1hr"
build_system = "Make"
prebuild_cmds = [
"git clone https://github.com/QuEST-Kit/QuEST.git",
"source cmake_questQFT.sh qft",
]
builddir = "build"
executable = "build/qft"
executable_opts = ["44"]
modules = ["cmake/3.29.4"]

@run_before("compile")
def prepare_build(self):
self.prebuild_cmd = ["git clone https://github.com/QuEST-Kit/QuEST.git .", "source cmake_questQFT.sh qft"]

@run_before("run")
def set_num_nodes(self):
self.job.options = [f"--nodes={self.num_nodes}"]

@sanity_function
def assert_finished(self):
"""Sanity check that simulation finished successfully"""
return sn.assert_found("Total run time:", self.stdout)


# @performance_function("seconds", perf_key="performance")
# def extract_perf(self):
# """Extract performance value to compare with reference value"""
# return sn.extractsingle(
# r"Averaged time per step \(s\):\s+(?P<steptime>\S+)",
# self.stdout,
# "time",
# float,
# )
61 changes: 61 additions & 0 deletions tests/apps/quest/QuestLarge.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env python3

# Based on original work from:
# Copyright 2016-2022 Swiss National Supercomputing Centre (CSCS/ETH Zurich)
# ReFrame Project Developers. See the top-level LICENSE file for details.
# SPDX-License-Identifier: BSD-3-Clause

import reframe as rfm
import reframe.utility.sanity as sn


@rfm.simple_test
class QuestQFTLargeTest(rfm.RegressionTest):
"""Quest Large 512 node Test"""

valid_systems = ["archer2:compute-capability"]
valid_prog_environs = ["PrgEnv-gnu"]

tags = {"performance", "largescale", "applications"}

num_nodes = 512
num_tasks_per_node = 1
num_cpus_per_task = 128
num_tasks = num_nodes * num_tasks_per_node

env_vars = {"OMP_NUM_THREADS": str(num_cpus_per_task), "OMP_PLACES": "cores"}

time_limit = "20m"
build_system = "Make"
prebuild_cmds = [
"git clone https://github.com/QuEST-Kit/QuEST.git",
"source cmake_questQFT.sh qft",
]
builddir = "build"
executable = "build/qft"
executable_opts = ["41"]
modules = ["cmake/3.29.4"]

@run_before("compile")
def prepare_build(self):
self.prebuild_cmd = ["git clone https://github.com/QuEST-Kit/QuEST.git .", "source cmake_questQFT.sh qft"]

@run_before("run")
def set_num_nodes(self):
self.job.options = [f"--nodes={self.num_nodes}"]

@sanity_function
def assert_finished(self):
"""Sanity check that simulation finished successfully"""
return sn.assert_found("Total run time:", self.stdout)


# @performance_function("seconds", perf_key="performance")
# def extract_perf(self):
# """Extract performance value to compare with reference value"""
# return sn.extractsingle(
# r"Averaged time per step \(s\):\s+(?P<steptime>\S+)",
# self.stdout,
# "time",
# float,
# )
26 changes: 26 additions & 0 deletions tests/apps/quest/src/cmake_questQFT.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash

TARGET=${1}
BUILD_DIR=build
SOURCE_DIR=QuEST

mkdir -p ${BUILD_DIR}
cd ${BUILD_DIR}

USER_SOURCE=../${TARGET}.cpp
OUTPUT_EXE=${TARGET}
DISTRIBUTED=1
MULTITHREADED=1
GPUACCELERATED=0

CC=cc
CXX=CC

cmake ../${SOURCE_DIR} \
-DCMAKE_C_COMPILER=${CC} \
-DCMAKE_CXX_COMPILER=${CXX} \
-DUSER_SOURCE=${USER_SOURCE} \
-DOUTPUT_EXE=${OUTPUT_EXE} \
-DDISTRIBUTED=${DISTRIBUTED} \
-DMULTITHREADED=${MULTITHREADED} \
-DGPUACCELERATED=${GPUACCELERATED}
156 changes: 156 additions & 0 deletions tests/apps/quest/src/qft.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "QuEST.h"

double calcPhaseShif(const int);
void qftQubit(Qureg, const int, const int);
void qft(Qureg, const int);
void writeState(const int * const, const size_t);
void getMonoTime(struct timespec *);
double getElapsedSeconds(const struct timespec * const,
const struct timespec * const);

int main (int argc, char *argv[])
{
int num_qubits;

if (argc < 2) {
num_qubits = 4;
} else if (argc > 2) {
printf("Error: Too many arguments! Usage: ./qft $NUMBER_OF_QUBITS\n");
return -1;
} else {
// arcg == 2
num_qubits = atoi(argv[1]);
if (num_qubits < 1) {
printf("Error: num_qubits < 1, you requested %d qubits\n", num_qubits);
return -1;
}
}

struct timespec run_start, run_stop;
struct timespec qft_start, qft_stop;
double run_time, qft_time;

getMonoTime(&run_start);

// initialise QuEST
QuESTEnv quenv = createQuESTEnv();

// create quantum register
Qureg qureg = createQureg(num_qubits, quenv);

if (!quenv.rank)
printf("Simulating %d-Qubit QFT\n\n", num_qubits);

// initialise input register to |0..0>
initZeroState(qureg);

// report model
if (!quenv.rank) {
reportQuregParams(qureg);
printf("\n");
reportQuESTEnv(quenv);
printf("\n");
}

getMonoTime(&qft_start);

// apply QFT to input register
qft(qureg, num_qubits);

getMonoTime(&qft_stop);

if (!quenv.rank)
printf("Total number of gates: %d\n", (num_qubits * (num_qubits+1))/2 );

// results
qreal prob_0 = getProbAmp(qureg, 0);
if (!quenv.rank) {
printf("Measured probability amplitude of |0..0> state: %g\n", prob_0);
printf("Calculated probability amplitude of |0..0>, C0 = 1 / 2^%d: %g\n",
num_qubits, 1.0 / pow(2,num_qubits));

printf("Measuring final state: (all probabilities should be 0.5)\n");
}

int * state = (int *) malloc(num_qubits * sizeof(int));
qreal * probs = (qreal *) malloc(num_qubits * sizeof(qreal));
for (int n = 0; n < num_qubits; ++n) {
state[n] = measureWithStats(qureg, n, probs+n);
}
if (!quenv.rank) {
for (int n = 0; n < num_qubits; ++n)
printf("Qubit %d measured in state %d with probability %g\n",
n, state[n], probs[n]);
printf("\n");
printf("Final state:\n");
writeState(state, num_qubits);
}

// free resources and stop timer
free(state);
free(probs);
destroyQureg(qureg, quenv);

getMonoTime(&run_stop);

qft_time = getElapsedSeconds(&qft_start, &qft_stop);
run_time = getElapsedSeconds(&run_start, &run_stop);

if (!quenv.rank)
printf("QFT run time: %gs\nTotal run time: %gs\n", qft_time, run_time);

// destroy QuESTEnv late because we need MPI rank
destroyQuESTEnv(quenv);

return 0;
}

double calcPhaseShift(const int M) {
return ( M_PI / pow(2, (M-1)) );
}

void qftQubit(Qureg qureg, const int num_qubits, const int QUBIT_ID) {
int control_id = 0;
double angle = 0.0;

hadamard(qureg, QUBIT_ID);
int m = 2;
for (int control = QUBIT_ID+1; control < num_qubits; ++control) {
angle = calcPhaseShift(m++);
controlledPhaseShift(qureg, control, QUBIT_ID, angle);
}

return;
}

void qft(Qureg qureg, const int num_qubits) {
for (int qid = 0; qid < num_qubits; ++qid)
qftQubit(qureg, num_qubits, qid);
return;
}

void writeState(const int * const STATE, const size_t num_qubits) {
printf("|");
for (size_t n = 0; n < num_qubits; ++n) printf("%d", STATE[n]);
printf(">\n");
return;
}

void getMonoTime(struct timespec * time) {
clock_gettime(CLOCK_MONOTONIC, time);
return;
}

double getElapsedSeconds(const struct timespec * const start,
const struct timespec * const stop) {
const unsigned long BILLION = 1000000000UL;
const unsigned long long TOTAL_NS =
BILLION * (stop->tv_sec - start->tv_sec)
+ (stop->tv_nsec - start->tv_nsec);

return (double) TOTAL_NS / BILLION;
}
Loading