Skip to content

[SPARK-32907][ML][PYTHON] adaptively blockify instances - LinearSVC - #30009

Closed
zhengruifeng wants to merge 11 commits into
apache:masterfrom
zhengruifeng:adaptively_blockify_linear_svc_II
Closed

[SPARK-32907][ML][PYTHON] adaptively blockify instances - LinearSVC#30009
zhengruifeng wants to merge 11 commits into
apache:masterfrom
zhengruifeng:adaptively_blockify_linear_svc_II

Conversation

@zhengruifeng

@zhengruifengzhengruifeng commented Oct 12, 2020

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

1, use maxBlockSizeInMB instead of blockSize(#rows) to control the stacking of vectors;
2, infer an appropriate maxBlockSizeInMB if set 0;

Why are the changes needed?

the performance gain is mainly related to the nnz of block.

f2jBLAS
Duration(millisecond)branch 3.0 ImplblockSizeInMB=0.0625blockSizeInMB=0.125blockSizeInMB=0.25blockSizeInMB=0.5blockSizeInMB=1blockSizeInMB=2blockSizeInMB=4blockSizeInMB=8blockSizeInMB=16blockSizeInMB=32blockSizeInMB=64blockSizeInMB=128
epsilon(100%)326481261432571024726253952584026846259272743126190260562634727204
epsilon3000(67%)455247358933436634985383873890140426400443916138767399653952339108
epsilon4000(50%)306390422564116443748486385089250986510915107251289516525331252146
epsilon5000(40%)307619436394299244743508005193951871521905385052607510625250951570
epsilon10000(20%)310070583715592156317566185369452131517685172852233518815165352440
epsilon20000(10%)3165651091939512182764696536076456066533715282252872527695252753508
epsilon200000(1%)336181156972110693556737183750432182301453931109269432787039839268189081787
Speedup
epsilon(100%)112.4882760212.6985997713.2039553512.8561134112.6347136212.1612530712.5923168911.9018993112.4658648312.529973912.3915815812.00121306
epsilon3000(67%)112.6834480313.247017413.0126339911.8594055311.7027068711.2612427611.3686694611.6250095811.7431578411.3911422511.5185335111.64076404
epsilon4000(50%)17.2508046197.4431542127.0035201616.2993955346.0203961336.009296675.9969466255.9991776325.9737955515.9318129025.7471113455.875618456
epsilon5000(40%)17.0491761967.1552614446.8752430556.0554921265.922697785.9304621085.8942134515.7125162495.8474917796.0244212925.8584052265.965076595
epsilon10000(20%)15.3120556445.5447863955.5057975395.47652695.7747606815.9479004815.989607485.9942390975.936285495.9765617476.0029427145.912852784
epsilon20000(10%)12.8991327283.3280243063.8249117974.5448867965.2097459025.646291875.9314046955.9930521375.9873846275.9990714256.0267100735.916218136
epsilon200000(1%)10.2141660840.3143773580.4989936440.8963798821.5404893922.3122227343.030678113.5639954633.8624179974.0056835784.1052753694.110445425
OpenBLAS
Duration(millisecond)branch 3.0 ImplblockSizeInMB=0.0625blockSizeInMB=0.125blockSizeInMB=0.25blockSizeInMB=0.5blockSizeInMB=1blockSizeInMB=2blockSizeInMB=4blockSizeInMB=8blockSizeInMB=16blockSizeInMB=32blockSizeInMB=64blockSizeInMB=128
epsilon(100%)299119260472504925239280013513836438362793611435111354283629535197
epsilon3000(67%)439798333213442334336389065175654138540855341254766544255422154842
epsilon4000(50%)302963429604067843483482545088854990526475194751843528915341052020
epsilon5000(40%)303569442254496145065517685277651930535875310451833521385257453756
epsilon10000(20%)307403584475599356757566945403852734520735205152150519865240752390
epsilon20000(10%)3133441075809467983329702266099657130554615464152712525415310153312
epsilon200000(1%)334679164272610731486544813649742138811402481075799175785090819408049280250
Speedup
epsilon(100%)111.4838177111.9413549411.8514600410.682439918.5126928118.2089851258.2449626518.2826327748.5192389858.4430111788.2413280078.498423161
epsilon3000(67%)113.1988235612.776283312.8086556411.304117628.4975268578.1236469768.1316076558.2340672518.0304933728.0808084528.1112115238.01936472
epsilon4000(50%)17.0522113597.447834216.9673895556.2785054095.9535253895.5094198955.7546108995.8321558515.8438554875.7280633765.6724021725.823971549
epsilon5000(40%)16.864194466.7518293636.7362476425.8640279715.7520274375.8457346435.6649747145.7164996995.8566743195.8224135955.7741278965.647164968
epsilon10000(20%)15.2595171695.4900255395.4161248835.4221434375.6886450285.8293131575.9033088165.9058039235.8945925225.9131881665.8656858825.867589235
epsilon20000(10%)12.9126603463.3095406583.7603235374.4619371745.1371237465.484754075.6498079735.7345949015.9444528765.9637996995.9009058215.87755102
epsilon200000(1%)10.2037339150.3118665830.5113654940.9169940871.5647907012.386337063.1110067953.6474492413.9332353984.0844398344.1579163154.170454829

Does this PR introduce any user-facing change?

yes, param blockSize -> blockSizeInMB in master

How was this patch tested?

added testsuites and performance test (result attached in ticket)

@zhengruifeng

Copy link
Copy Markdown
ContributorAuthor

ping @WeichenXu123

@zero323 I send a new PR here, thanks for reviewing. I tried to verify consistency of annotations locally, but the following cmd failed:

mypy --no-incremental --config python/mypy.ini python/pyspark
python/pyspark/ml/linalg/__init__.pyi:25: error: misplaced type annotation

I installed mypy by sudo apt install mypy in ubuntu 18.04,
I am not very similar to mypy, do I need to configure it somewhere?

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test starting
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/34257/

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test status success
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/34257/

@SparkQA

Copy link
Copy Markdown

Test build #129653 has finished for PR 30009 at commit eb0cf6b.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds the following public classes (experimental):
  • trait HasBlockSizeInMB extends Params
  • class HasBlockSizeInMB(Params):

@zero323

Copy link
Copy Markdown
Member

@zero323 I send a new PR here, thanks for reviewing. I tried to verify consistency of annotations locally, but the following cmd failed:

mypy --no-incremental --config python/mypy.ini python/pyspark
python/pyspark/ml/linalg/__init__.pyi:25: error: misplaced type annotation

I installed mypy by sudo apt install mypy in ubuntu 18.04,
I am not very similar to mypy, do I need to configure it somewhere?

No additional configuration should be required, but the version from Ubuntu errors is pretty old, and at first glance it doesn't support error codes ([import] part).

Personally I'd recommend either venv or miniconda, but if you want quick fix, installing pip and making user install should do the trick

sudo apt purge mypy
sudo apt install python3-pip
pip install mypy

I've checked things on my side (mypy 0.790, current stable), for both master and this PR, and things look good.

@WeichenXu123WeichenXu123 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made first pass.
Overall good.

Comment threadmllib/src/main/scala/org/apache/spark/ml/feature/Instance.scala Outdated
Comment threadmllib/src/main/scala/org/apache/spark/ml/feature/Instance.scala Outdated
Comment threadmllib/src/main/scala/org/apache/spark/ml/feature/Instance.scala Outdated
@zhengruifeng

Copy link
Copy Markdown
ContributorAuthor

@zero323 Yes, that is because the version installed via sudo apt install mypy is too old (0.560).
pip install mypy works for me. Thank you!

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test starting
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/34330/

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test status success
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/34330/

@SparkQA

Copy link
Copy Markdown

Test build #129724 has finished for PR 30009 at commit 9cd1053.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test starting
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/34346/

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test status success
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/34346/

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test starting
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/34348/

@SparkQA

Copy link
Copy Markdown

Test build #129740 has finished for PR 30009 at commit 08cf27d.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@SparkQA

Copy link
Copy Markdown

Test build #129742 has finished for PR 30009 at commit 9245263.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test status success
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/34348/

@WeichenXu123WeichenXu123 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's simplify logic:

new Iterator[T] {
override def hasNext: Boolean = rowIter.hasNext()
override def next(): T = {
val buff = ..
val buffNnz = 0
while (rowIter.hasNext() && estimateSize(...) < maxMemUsage) {
val row = rowIter.next()
buff.append(row)
nnz += ...
}
// the block mem usage may slightly exceed threshold, not a big issue.
// and this ensure even if one row exceed block limit, each block has one row
InstanceBlock.fromBuff(buff)
}
}

Comment threadmllib/src/main/scala/org/apache/spark/ml/feature/Instance.scala Outdated
@zhengruifeng

Copy link
Copy Markdown
ContributorAuthor

retest this please

@SparkQA

Copy link
Copy Markdown

Test build #129756 has finished for PR 30009 at commit df02e98.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test starting
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/34362/

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test status success
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/34362/

@zhengruifeng

Copy link
Copy Markdown
ContributorAuthor

retest this please

@SparkQA

Copy link
Copy Markdown

Test build #129786 has finished for PR 30009 at commit df02e98.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test starting
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/34393/

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test status success
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/34393/

@WeichenXu123WeichenXu123 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's paste benchmark result on the PR description.

Have you benchmark on other BLAS besides f2jBLAS ?

s"which may hurt performance in high-level BLAS.")
}
if (actualBlockSizeInMB == 0) {
val avgNNZ = summarizer.numNonzeros.activeIterator.map(_._2 / summarizer.count).sum

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will the additional summarizer consume time ?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, one more metric numNonZeros will be computed.
Since it still need only one pass, I think the additional time should not be significant.

Comment on lines +186 to +202
if (dim <= avgNNZ * 3) {
0.25
} else {
64.0
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Document why choose the value ?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current strategy is quitely simple, I think we may use a complex costmodel if necessay in the future.

@WeichenXu123

Copy link
Copy Markdown
Contributor

@mengxr Do you want to take a look ?


// instances larger than maxMemUsage
val bigInstance = Instance(-1.0, 2.0, Vectors.dense(Array.fill(10000)(1.0)))
InstanceBlock.blokifyWithMaxMemUsage(Iterator.fill(10)(bigInstance), 64).size

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verify block contains 1 row.

intercept[IllegalArgumentException] {
InstanceBlock.blokifyWithMaxMemUsage(Iterator.apply(instance1, bigInstance), 64).size
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add test:

  • Generate a sparse and dense instance mixed list (a list which some segment is dense but others are very sparse), verify each block size won't exceed the blockMem limit too much. (Such as: (actual block mem size)/confg <= 1.1 ?)

@zhengruifeng

Copy link
Copy Markdown
ContributorAuthor

Have you benchmark on other BLAS besides f2jBLAS ?

@WeichenXu123 both f2jBlas and openBlas were benchmarked, and recorded in the result excel file.

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test starting
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/35564/

@SparkQA

Copy link
Copy Markdown

Test build #130958 has finished for PR 30009 at commit a82e5f5.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test status success
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/35564/

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test starting
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/35566/

@SparkQA

Copy link
Copy Markdown

Test build #130960 has finished for PR 30009 at commit a69ca83.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds the following public classes (experimental):
  • trait HasMaxBlockSizeInMB extends Params
  • class HasMaxBlockSizeInMB(Params):

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test status failure
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/35566/

@zhengruifeng

Copy link
Copy Markdown
ContributorAuthor

retest this please

@SparkQA

Copy link
Copy Markdown

Test build #130969 has finished for PR 30009 at commit a69ca83.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds the following public classes (experimental):
  • trait HasMaxBlockSizeInMB extends Params
  • class HasMaxBlockSizeInMB(Params):

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test starting
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/35575/

@zhengruifengzhengruifeng changed the title [SPARK-32907][ML] adaptively blockify instances - LinearSVC[SPARK-32907][ML][PYTHON] adaptively blockify instances - LinearSVCNov 12, 2020
@SparkQA

Copy link
Copy Markdown

Kubernetes integration test status failure
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/35575/

@zhengruifeng

Copy link
Copy Markdown
ContributorAuthor

retest this please

@SparkQA

Copy link
Copy Markdown

Test build #130977 has finished for PR 30009 at commit a69ca83.

  • This patch fails due to an unknown error code, -9.
  • This patch merges cleanly.
  • This patch adds the following public classes (experimental):
  • trait HasMaxBlockSizeInMB extends Params
  • class HasMaxBlockSizeInMB(Params):

@zhengruifeng

Copy link
Copy Markdown
ContributorAuthor

retest this please

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test starting
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/35582/

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test status failure
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/35582/

@SparkQA

Copy link
Copy Markdown

Test build #130981 has finished for PR 30009 at commit a69ca83.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds the following public classes (experimental):
  • trait HasMaxBlockSizeInMB extends Params
  • class HasMaxBlockSizeInMB(Params):

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test starting
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/35587/

@SparkQA

Copy link
Copy Markdown

Kubernetes integration test status success
URL: https://amplab.cs.berkeley.edu/jenkins/job/SparkPullRequestBuilder-K8s/35587/

@WeichenXu123WeichenXu123 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@WeichenXu123

Copy link
Copy Markdown
Contributor

Merged to master. Thanks!

@zhengruifeng
zhengruifeng deleted the adaptively_blockify_linear_svc_II branch November 12, 2020 11:57
@zhengruifeng

Copy link
Copy Markdown
ContributorAuthor

Thanks @WeichenXu123@mengxr@zero323 for review!

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@zhengruifeng@SparkQA@zero323@WeichenXu123@mengxr