Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
H
homework_parallel
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
roset.alwzrah
homework_parallel
Commits
cba75c4e
Commit
cba75c4e
authored
Mar 21, 2023
by
roset.alwzrah
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Student Analytics
parent
8bca5127
Pipeline
#180
failed with stages
Changes
4
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
419 additions
and
5 deletions
+419
-5
workspace.xml
.idea/workspace.xml
+14
-5
Student.java
src/main/java/Resource/Student.java
+86
-0
StudentAnalytics.java
src/main/java/Service/StudentAnalytics.java
+150
-0
StudentAnalyticsTest.java
src/test/java/StudentAnalyticsTest.java
+169
-0
No files found.
.idea/workspace.xml
View file @
cba75c4e
...
...
@@ -4,9 +4,10 @@
<option
name=
"autoReloadType"
value=
"SELECTIVE"
/>
</component>
<component
name=
"ChangeListManager"
>
<list
default=
"true"
id=
"bd82bf16-4018-4075-b7d4-6d792f3cd58b"
name=
"Changes"
comment=
"Find the number of occurrences of a number in an array"
>
<change
afterPath=
"$PROJECT_DIR$/src/main/java/Service/Fibonacci.java"
afterDir=
"false"
/>
<change
afterPath=
"$PROJECT_DIR$/src/test/java/FibonacciTest.java"
afterDir=
"false"
/>
<list
default=
"true"
id=
"bd82bf16-4018-4075-b7d4-6d792f3cd58b"
name=
"Changes"
comment=
"calculate fibonacci number"
>
<change
afterPath=
"$PROJECT_DIR$/src/main/java/Resource/Student.java"
afterDir=
"false"
/>
<change
afterPath=
"$PROJECT_DIR$/src/main/java/Service/StudentAnalytics.java"
afterDir=
"false"
/>
<change
afterPath=
"$PROJECT_DIR$/src/test/java/StudentAnalyticsTest.java"
afterDir=
"false"
/>
<change
beforePath=
"$PROJECT_DIR$/.idea/workspace.xml"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/.idea/workspace.xml"
afterDir=
"false"
/>
</list>
<option
name=
"SHOW_DIALOG"
value=
"false"
/>
...
...
@@ -56,7 +57,14 @@
<option
name=
"project"
value=
"LOCAL"
/>
<updated>
1679420949412
</updated>
</task>
<option
name=
"localTasksCounter"
value=
"2"
/>
<task
id=
"LOCAL-00002"
summary=
"calculate fibonacci number"
>
<created>
1679421396058
</created>
<option
name=
"number"
value=
"00002"
/>
<option
name=
"presentableId"
value=
"LOCAL-00002"
/>
<option
name=
"project"
value=
"LOCAL"
/>
<updated>
1679421396058
</updated>
</task>
<option
name=
"localTasksCounter"
value=
"3"
/>
<servers
/>
</component>
<component
name=
"Vcs.Log.Tabs.Properties"
>
...
...
@@ -72,6 +80,7 @@
</component>
<component
name=
"VcsManagerConfiguration"
>
<MESSAGE
value=
"Find the number of occurrences of a number in an array"
/>
<option
name=
"LAST_COMMIT_MESSAGE"
value=
"Find the number of occurrences of a number in an array"
/>
<MESSAGE
value=
"calculate fibonacci number"
/>
<option
name=
"LAST_COMMIT_MESSAGE"
value=
"calculate fibonacci number"
/>
</component>
</project>
\ No newline at end of file
src/main/java/Resource/Student.java
0 → 100644
View file @
cba75c4e
package
Resource
;
/**
* A class representing a single student in a single class.
*/
public
final
class
Student
{
/**
* First name of the student.
*/
private
final
String
firstName
;
/**
* Surname of the student.
*/
private
final
String
lastName
;
/**
* Age of the student.
*/
private
final
double
age
;
/**
* Grade the student has received in the class so far.
*/
private
final
int
grade
;
/**
* Whether the student is currently enrolled, or has already completed the
* course.
*/
private
final
boolean
isCurrent
;
/**
* Constructor.
* @param setFirstName Student first name
* @param setLastName Student last name
* @param setAge Student age
* @param setGrade Student grade in course
* @param setIsCurrent Student currently enrolled?
*/
public
Student
(
final
String
setFirstName
,
final
String
setLastName
,
final
double
setAge
,
final
int
setGrade
,
final
boolean
setIsCurrent
)
{
this
.
firstName
=
setFirstName
;
this
.
lastName
=
setLastName
;
this
.
age
=
setAge
;
this
.
grade
=
setGrade
;
this
.
isCurrent
=
setIsCurrent
;
}
/**
* Get the first name of this student.
* @return The student's first name.
*/
public
String
getFirstName
()
{
return
firstName
;
}
/**
* Get the last name of this student.
* @return The student's last name.
*/
public
String
getLastName
()
{
return
lastName
;
}
/**
* Get the age of this student.
* @return The student's age.
*/
public
double
getAge
()
{
return
age
;
}
/**
* Get the grade this student has achieved in this course so far.
* @return The student's current grade.
*/
public
int
getGrade
()
{
return
grade
;
}
/**
* Check if this student is active, or has taken the course in the past.
* @return true if the student is currently enrolled, false otherwise
*/
public
boolean
checkIsCurrent
()
{
return
isCurrent
;
}
}
src/main/java/Service/StudentAnalytics.java
0 → 100644
View file @
cba75c4e
package
Service
;
import
Resource.Student
;
import
java.util.*
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
import
java.util.stream.Stream
;
/**
* A simple wrapper class for various analytics methods.
*/
public
final
class
StudentAnalytics
{
/**
* Sequentially computes the average age of all actively enrolled students
* using loops.
*
* @param studentArray Student data for the class.
* @return Average age of enrolled students
*/
public
double
averageAgeOfEnrolledStudentsImperative
(
final
Student
[]
studentArray
)
{
List
<
Student
>
activeStudents
=
new
ArrayList
<
Student
>();
for
(
Student
s
:
studentArray
)
{
if
(
s
.
checkIsCurrent
())
{
activeStudents
.
add
(
s
);
}
}
double
ageSum
=
0.0
;
for
(
Student
s
:
activeStudents
)
{
ageSum
+=
s
.
getAge
();
}
return
ageSum
/
(
double
)
activeStudents
.
size
();
}
/**
* TODO compute the average age of all actively enrolled students using
* parallel streams. This should mirror the functionality of
* averageAgeOfEnrolledStudentsImperative. This method should not use any
* loops.
*
* @param studentArray Student data for the class.
* @return Average age of enrolled students
*/
public
double
averageAgeOfEnrolledStudentsParallelStream
(
final
Student
[]
studentArray
)
{
double
avg
=
Stream
.
of
(
studentArray
).
parallel
().
filter
(
s
->
s
.
checkIsCurrent
()).
mapToDouble
(
s
->
s
.
getAge
()).
average
().
getAsDouble
();
return
avg
;
}
/**
* Sequentially computes the most common first name out of all students that
* are no longer active in the class using loops.
*
* @param studentArray Student data for the class.
* @return Most common first name of inactive students
*/
public
String
mostCommonFirstNameOfInactiveStudentsImperative
(
final
Student
[]
studentArray
)
{
List
<
Student
>
inactiveStudents
=
new
ArrayList
<
Student
>();
for
(
Student
s
:
studentArray
)
{
if
(!
s
.
checkIsCurrent
())
{
inactiveStudents
.
add
(
s
);
}
}
Map
<
String
,
Integer
>
nameCounts
=
new
HashMap
<
String
,
Integer
>();
for
(
Student
s
:
inactiveStudents
)
{
if
(
nameCounts
.
containsKey
(
s
.
getFirstName
()))
{
nameCounts
.
put
(
s
.
getFirstName
(),
new
Integer
(
nameCounts
.
get
(
s
.
getFirstName
())
+
1
));
}
else
{
nameCounts
.
put
(
s
.
getFirstName
(),
1
);
}
}
String
mostCommon
=
null
;
int
mostCommonCount
=
-
1
;
for
(
Map
.
Entry
<
String
,
Integer
>
entry
:
nameCounts
.
entrySet
())
{
if
(
mostCommon
==
null
||
entry
.
getValue
()
>
mostCommonCount
)
{
mostCommon
=
entry
.
getKey
();
mostCommonCount
=
entry
.
getValue
();
}
}
return
mostCommon
;
}
/**
* TODO compute the most common first name out of all students that are no
* longer active in the class using parallel streams. This should mirror the
* functionality of mostCommonFirstNameOfInactiveStudentsImperative. This
* method should not use any loops.
*
* @param studentArray Student data for the class.
* @return Most common first name of inactive students
*/
public
String
mostCommonFirstNameOfInactiveStudentsParallelStream
(
final
Student
[]
studentArray
)
{
String
mostCommon
=
null
;
mostCommon
=
Stream
.
of
(
studentArray
).
parallel
().
filter
(
s
->
!
s
.
checkIsCurrent
()).
map
(
s
->
s
.
getFirstName
())
.
collect
(
Collectors
.
groupingBy
(
Function
.
identity
(),
Collectors
.
counting
())).
entrySet
()
.
stream
().
max
(
Comparator
.
comparing
(
Map
.
Entry
::
getValue
))
.
get
().
getKey
();
return
mostCommon
;
}
/**
* Sequentially computes the number of students who have failed the course
* who are also older than 20 years old. A failing grade is anything below a
* 65. A student has only failed the course if they have a failing grade and
* they are not currently active.
*
* @param studentArray Student data for the class.
* @return Number of failed grades from students older than 20 years old.
*/
public
int
countNumberOfFailedStudentsOlderThan20Imperative
(
final
Student
[]
studentArray
)
{
int
count
=
0
;
for
(
Student
s
:
studentArray
)
{
if
(!
s
.
checkIsCurrent
()
&&
s
.
getAge
()
>
20
&&
s
.
getGrade
()
<
65
)
{
count
++;
}
}
return
count
;
}
/**
* TODO compute the number of students who have failed the course who are
* also older than 20 years old. A failing grade is anything below a 65. A
* student has only failed the course if they have a failing grade and they
* are not currently active. This should mirror the functionality of
* countNumberOfFailedStudentsOlderThan20Imperative. This method should not
* use any loops.
*
* @param studentArray Student data for the class.
* @return Number of failed grades from students older than 20 years old.
*/
public
int
countNumberOfFailedStudentsOlderThan20ParallelStream
(
final
Student
[]
studentArray
)
{
int
count
=
0
;
count
=
(
int
)
Stream
.
of
(
studentArray
).
parallel
().
filter
(
s
->
(!
s
.
checkIsCurrent
()
&&
s
.
getGrade
()<
65
&&
s
.
getAge
()>
20
)).
count
();
return
count
;
}
}
src/test/java/StudentAnalyticsTest.java
0 → 100644
View file @
cba75c4e
import
java.util.Random
;
import
junit.framework.TestCase
;
import
Service.StudentAnalytics
;
import
Resource.Student
;
public
class
StudentAnalyticsTest
extends
TestCase
{
final
static
int
REPEATS
=
10
;
private
final
static
String
[]
firstNames
=
{
"Sanjay"
,
"Yunming"
,
"John"
,
"Vivek"
,
"Shams"
,
"Max"
};
private
final
static
String
[]
lastNames
=
{
"Chatterjee"
,
"Zhang"
,
"Smith"
,
"Sarkar"
,
"Imam"
,
"Grossman"
};
private
static
int
getNCores
()
{
String
ncoresStr
=
System
.
getenv
(
"COURSERA_GRADER_NCORES"
);
if
(
ncoresStr
==
null
)
{
return
Runtime
.
getRuntime
().
availableProcessors
();
}
else
{
return
Integer
.
parseInt
(
ncoresStr
);
}
}
private
Student
[]
generateStudentData
()
{
final
int
N_STUDENTS
=
2000000
;
final
int
N_CURRENT_STUDENTS
=
600000
;
Student
[]
students
=
new
Student
[
N_STUDENTS
];
Random
r
=
new
Random
(
123
);
for
(
int
s
=
0
;
s
<
N_STUDENTS
;
s
++)
{
final
String
firstName
=
firstNames
[
r
.
nextInt
(
firstNames
.
length
)];
final
String
lastName
=
lastNames
[
r
.
nextInt
(
lastNames
.
length
)];
final
double
age
=
r
.
nextDouble
()
*
100.0
;
final
int
grade
=
1
+
r
.
nextInt
(
100
);
final
boolean
current
=
(
s
<
N_CURRENT_STUDENTS
);
students
[
s
]
=
new
Student
(
firstName
,
lastName
,
age
,
grade
,
current
);
}
return
students
;
}
private
double
averageAgeOfEnrolledStudentsHelper
(
final
int
repeats
)
{
final
Student
[]
students
=
generateStudentData
();
final
StudentAnalytics
analytics
=
new
StudentAnalytics
();
final
double
ref
=
analytics
.
averageAgeOfEnrolledStudentsImperative
(
students
);
final
long
startSequential
=
System
.
currentTimeMillis
();
for
(
int
r
=
0
;
r
<
repeats
;
r
++)
{
analytics
.
averageAgeOfEnrolledStudentsImperative
(
students
);
}
final
long
endSequential
=
System
.
currentTimeMillis
();
final
double
calc
=
analytics
.
averageAgeOfEnrolledStudentsParallelStream
(
students
);
final
double
err
=
Math
.
abs
(
calc
-
ref
);
final
String
msg
=
"Expected "
+
ref
+
" but found "
+
calc
+
", err = "
+
err
;
assertTrue
(
msg
,
err
<
1
E
-
5
);
final
long
startParallel
=
System
.
currentTimeMillis
();
for
(
int
r
=
0
;
r
<
repeats
;
r
++)
{
analytics
.
averageAgeOfEnrolledStudentsParallelStream
(
students
);
}
final
long
endParallel
=
System
.
currentTimeMillis
();
return
(
double
)(
endSequential
-
startSequential
)
/
(
double
)(
endParallel
-
startParallel
);
}
/*
* Test correctness of averageAgeOfEnrolledStudentsParallelStream.
*/
public
void
testAverageAgeOfEnrolledStudents
()
{
averageAgeOfEnrolledStudentsHelper
(
1
);
}
/*
* Test performance of averageAgeOfEnrolledStudentsParallelStream.
*/
public
void
testAverageAgeOfEnrolledStudentsPerf
()
{
final
int
ncores
=
getNCores
();
final
double
speedup
=
averageAgeOfEnrolledStudentsHelper
(
REPEATS
);
String
msg
=
"Expected parallel version to run at least 1.2x faster but speedup was "
+
speedup
;
assertTrue
(
msg
,
speedup
>
1.2
);
}
private
double
mostCommonFirstNameOfInactiveStudentsHelper
(
final
int
repeats
)
{
final
Student
[]
students
=
generateStudentData
();
final
StudentAnalytics
analytics
=
new
StudentAnalytics
();
final
String
ref
=
analytics
.
mostCommonFirstNameOfInactiveStudentsImperative
(
students
);
final
long
startSequential
=
System
.
currentTimeMillis
();
for
(
int
r
=
0
;
r
<
repeats
;
r
++)
{
analytics
.
mostCommonFirstNameOfInactiveStudentsImperative
(
students
);
}
final
long
endSequential
=
System
.
currentTimeMillis
();
final
String
calc
=
analytics
.
mostCommonFirstNameOfInactiveStudentsParallelStream
(
students
);
assertEquals
(
"Mismatch in calculated values"
,
ref
,
calc
);
final
long
startParallel
=
System
.
currentTimeMillis
();
for
(
int
r
=
0
;
r
<
repeats
;
r
++)
{
analytics
.
mostCommonFirstNameOfInactiveStudentsParallelStream
(
students
);
}
final
long
endParallel
=
System
.
currentTimeMillis
();
return
(
double
)(
endSequential
-
startSequential
)
/
(
double
)(
endParallel
-
startParallel
);
}
/*
* Test correctness of mostCommonFirstNameOfInactiveStudentsParallelStream.
*/
public
void
testMostCommonFirstNameOfInactiveStudents
()
{
mostCommonFirstNameOfInactiveStudentsHelper
(
1
);
}
/*
* Test performance of mostCommonFirstNameOfInactiveStudentsParallelStream.
*/
public
void
testMostCommonFirstNameOfInactiveStudentsPerf
()
{
final
int
ncores
=
getNCores
();
final
double
speedup
=
mostCommonFirstNameOfInactiveStudentsHelper
(
REPEATS
);
final
double
expectedSpeedup
=
(
double
)
ncores
*
0.5
;
String
msg
=
"Expected speedup to be at least "
+
expectedSpeedup
+
" but was "
+
speedup
;
assertTrue
(
msg
,
speedup
>=
expectedSpeedup
);
}
private
double
countNumberOfFailedStudentsOlderThan20Helper
(
final
int
repeats
)
{
final
Student
[]
students
=
generateStudentData
();
final
StudentAnalytics
analytics
=
new
StudentAnalytics
();
final
int
ref
=
analytics
.
countNumberOfFailedStudentsOlderThan20Imperative
(
students
);
final
long
startSequential
=
System
.
currentTimeMillis
();
for
(
int
r
=
0
;
r
<
repeats
;
r
++)
{
analytics
.
countNumberOfFailedStudentsOlderThan20Imperative
(
students
);
}
final
long
endSequential
=
System
.
currentTimeMillis
();
final
int
calc
=
analytics
.
countNumberOfFailedStudentsOlderThan20ParallelStream
(
students
);
assertEquals
(
"Mismatch in calculated values"
,
ref
,
calc
);
final
long
startParallel
=
System
.
currentTimeMillis
();
for
(
int
r
=
0
;
r
<
repeats
;
r
++)
{
analytics
.
countNumberOfFailedStudentsOlderThan20ParallelStream
(
students
);
}
final
long
endParallel
=
System
.
currentTimeMillis
();
return
(
double
)(
endSequential
-
startSequential
)
/
(
double
)(
endParallel
-
startParallel
);
}
/*
* Test correctness of countNumberOfFailedStudentsOlderThan20ParallelStream.
*/
public
void
testCountNumberOfFailedStudentsOlderThan20
()
{
countNumberOfFailedStudentsOlderThan20Helper
(
1
);
}
/*
* Test performance of countNumberOfFailedStudentsOlderThan20ParallelStream.
*/
public
void
testCountNumberOfFailedStudentsOlderThan20Perf
()
{
final
int
ncores
=
getNCores
();
final
double
speedup
=
countNumberOfFailedStudentsOlderThan20Helper
(
REPEATS
);
String
msg
=
"Expected parallel version to run at least 1.2x faster but speedup was "
+
speedup
;
assertTrue
(
msg
,
speedup
>
1.2
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment