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
You need to sign in or sign up before continuing.
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 @@
...
@@ -4,9 +4,10 @@
<option
name=
"autoReloadType"
value=
"SELECTIVE"
/>
<option
name=
"autoReloadType"
value=
"SELECTIVE"
/>
</component>
</component>
<component
name=
"ChangeListManager"
>
<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"
>
<list
default=
"true"
id=
"bd82bf16-4018-4075-b7d4-6d792f3cd58b"
name=
"Changes"
comment=
"calculate fibonacci number"
>
<change
afterPath=
"$PROJECT_DIR$/src/main/java/Service/Fibonacci.java"
afterDir=
"false"
/>
<change
afterPath=
"$PROJECT_DIR$/src/main/java/Resource/Student.java"
afterDir=
"false"
/>
<change
afterPath=
"$PROJECT_DIR$/src/test/java/FibonacciTest.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"
/>
<change
beforePath=
"$PROJECT_DIR$/.idea/workspace.xml"
beforeDir=
"false"
afterPath=
"$PROJECT_DIR$/.idea/workspace.xml"
afterDir=
"false"
/>
</list>
</list>
<option
name=
"SHOW_DIALOG"
value=
"false"
/>
<option
name=
"SHOW_DIALOG"
value=
"false"
/>
...
@@ -56,7 +57,14 @@
...
@@ -56,7 +57,14 @@
<option
name=
"project"
value=
"LOCAL"
/>
<option
name=
"project"
value=
"LOCAL"
/>
<updated>
1679420949412
</updated>
<updated>
1679420949412
</updated>
</task>
</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
/>
<servers
/>
</component>
</component>
<component
name=
"Vcs.Log.Tabs.Properties"
>
<component
name=
"Vcs.Log.Tabs.Properties"
>
...
@@ -72,6 +80,7 @@
...
@@ -72,6 +80,7 @@
</component>
</component>
<component
name=
"VcsManagerConfiguration"
>
<component
name=
"VcsManagerConfiguration"
>
<MESSAGE
value=
"Find the number of occurrences of a number in an array"
/>
<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>
</component>
</project>
</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